Help us shape the future of Go! Take the 2026 Go Developer Survey

urn

package module
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 26, 2024 License: MIT Imports: 4 Imported by: 181

README

Build Coverage Documentation

A parser for URNs.

As seen on RFC 2141.

API documentation.

Starting with version 1.3 this library also supports RFC 7643 SCIM URNs.

Installation

go get github.com/leodido/go-urn

Features

  1. RFC 2141 URNs parsing (default)
  2. RFC 7643 SCIM URNs parsing
  3. Fallback mode: first try to parse the input as a RFC 7643 SCIM URN, then fallback to RFC 2141 URN generic format.
  4. Normalization as per RFC 2141
  5. Lexical equivalence as per RFC 2141
  6. Precise, fine-grained errors

Performances

This implementation results to be really fast.

Usually below ½ microsecond on my machine1.

Notice it also performs, while parsing:

  1. fine-grained and informative erroring
  2. specific-string normalization
Parse/ok/00/urn:a:b______________________________________/-10    71113568    84.88 ns/op    211 B/op    3 allocs/op
Parse/ok/01/URN:foo:a123,456_____________________________/-10    49303754    126.1 ns/op    232 B/op    6 allocs/op
Parse/ok/02/urn:foo:a123%2c456___________________________/-10    46723497    122.1 ns/op    240 B/op    6 allocs/op
Parse/ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-10    34231863    175.1 ns/op    312 B/op    6 allocs/op
Parse/ok/04/urn:ietf:params:scim:schemas:extension:enterp/-10    25406808    233.6 ns/op    344 B/op    6 allocs/op
Parse/ok/05/urn:ietf:params:scim:schemas:extension:enterp/-10    22353264    265.6 ns/op    376 B/op    6 allocs/op
Parse/ok/06/urn:burnout:nss______________________________/-10    52932087    112.9 ns/op    224 B/op    6 allocs/op
Parse/ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-10    45005554    134.3 ns/op    243 B/op    4 allocs/op
Parse/ok/08/urn:urnurnurn:urn____________________________/-10    46788519    124.7 ns/op    229 B/op    6 allocs/op
Parse/ok/09/urn:ciao:@!=%2c(xyz)+a,b.*@g=$_'_____________/-10    39037539    153.8 ns/op    264 B/op    6 allocs/op
Parse/ok/10/URN:x:abc%1dz%2f%3az_________________________/-10    45692990    121.4 ns/op    243 B/op    5 allocs/op
Parse/no/11/URN:-xxx:x___________________________________/-10    26935477    221.1 ns/op    355 B/op    5 allocs/op
Parse/no/12/urn::colon:nss_______________________________/-10    25088925    232.4 ns/op    355 B/op    5 allocs/op
Parse/no/13/urn:abcdefghilmnopqrstuvzabcdefghilmn:specifi/-10    21206989    295.1 ns/op    355 B/op    5 allocs/op
Parse/no/14/URN:a!?:x____________________________________/-10    26705482    223.5 ns/op    355 B/op    5 allocs/op
Parse/no/15/urn:urn:NSS__________________________________/-10    31609467    202.1 ns/op    307 B/op    5 allocs/op
Parse/no/16/urn:white_space:NSS__________________________/-10    26144792    232.2 ns/op    355 B/op    5 allocs/op
Parse/no/17/urn:concat:no_spaces_________________________/-10    23717426    251.1 ns/op    346 B/op    6 allocs/op
Parse/no/18/urn:a:/______________________________________/-10    27442077    221.9 ns/op    339 B/op    5 allocs/op
Parse/no/19/urn:UrN:NSS__________________________________/-10    32096002    187.4 ns/op    307 B/op    5 allocs/op
  • [1]: Apple M1 Pro

Example

For more examples take a look at the examples file.

package main

import (
	"fmt"
	"github.com/leodido/go-urn"
)

func main() {
	var uid = "URN:foo:a123,456"

    // Parse the input string as a RFC 2141 URN only
	u, e := urn.NewMachine().Parse(uid)
	if e != nil {
		fmt.Errorf(err)

		return
	}

	fmt.Println(u.ID)
	fmt.Println(u.SS)

	// Output:
	// foo
	// a123,456
}
package main

import (
	"fmt"
	"github.com/leodido/go-urn"
)

func main() {
	var uid = "URN:foo:a123,456"

    // Parse the input string as a RFC 2141 URN only
	u, ok := urn.Parse([]byte(uid))
	if !ok {
		panic("error parsing urn")
	}

	fmt.Println(u.ID)
	fmt.Println(u.SS)

	// Output:
	// foo
	// a123,456
}
package main

import (
	"fmt"
	"github.com/leodido/go-urn"
)

func main() {
	input := "urn:ietf:params:scim:api:messages:2.0:ListResponse"

	// Parsing the input string as a RFC 7643 SCIM URN
	u, ok := urn.Parse([]byte(input), urn.WithParsingMode(urn.RFC7643Only))
	if !ok {
		panic("error parsing urn")
	}

	fmt.Println(u.IsSCIM())
	scim := u.SCIM()
	fmt.Println(scim.Type.String())
	fmt.Println(scim.Name)
	fmt.Println(scim.Other)

	// Output:
	// true
	// api
	// messages
	// 2.0:ListResponse
}

Documentation

Index

Examples

Constants

View Source
const DefaultParsingMode = RFC2141Only

Variables

This section is empty.

Functions

This section is empty.

Types

type Kind added in v1.3.0

type Kind int
const (
	NONE Kind = iota
	RFC2141
	RFC7643
)

type Machine

type Machine interface {
	Error() error
	Parse(input []byte) (*URN, error)
	WithParsingMode(ParsingMode)
}

Machine is the interface representing the FSM

func NewMachine

func NewMachine(options ...Option) Machine

NewMachine creates a new FSM able to parse RFC 2141 strings.

type Option added in v1.3.0

type Option func(Machine)

func WithParsingMode added in v1.3.0

func WithParsingMode(mode ParsingMode) Option

type ParsingMode added in v1.3.0

type ParsingMode int
const (
	All ParsingMode = iota // Fallback mode
	RFC2141Only
	RFC7643Only
)

type SCIM added in v1.3.0

type SCIM struct {
	Type  scimschema.Type
	Name  string
	Other string
	// contains filtered or unexported fields
}

type URN

type URN struct {
	ID string // Namespace identifier (NID)
	SS string // Namespace specific string (NSS)
	// contains filtered or unexported fields
}

URN represents an Uniform Resource Name.

The general form represented is:

urn:<id>:<ss>

Details at https://tools.ietf.org/html/rfc2141.

func Parse

func Parse(u []byte, options ...Option) (*URN, bool)

Parse is responsible to create an URN instance from a byte array matching the correct URN syntax (RFC 2141).

Example
package main

import (
	"fmt"

	"github.com/leodido/go-urn"
)

func main() {
	var uid = "URN:foo:a123,456"

	if u, ok := urn.Parse([]byte(uid)); ok {
		fmt.Println(u.ID)
		fmt.Println(u.SS)
		fmt.Println(u.SCIM())
	}

}
Output:
foo
a123,456
<nil>
Example (Scim)
package main

import (
	"fmt"

	"github.com/leodido/go-urn"
)

func main() {
	input := "urn:ietf:params:scim:api:messages:2.0:ListResponse"

	u, ok := urn.Parse([]byte(input), urn.WithParsingMode(urn.RFC7643Only))
	if !ok {
		panic("invalid SCIM urn")
	}
	data, err := u.MarshalJSON()
	if err != nil {
		panic("couldn't marshal")
	}
	fmt.Println(string(data))
	fmt.Println(u.IsSCIM())
	scim := u.SCIM()
	fmt.Println(scim.Type.String())
	fmt.Println(scim.Name)
	fmt.Println(scim.Other)

}
Output:
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
true
api
messages
2.0:ListResponse

func (*URN) Equal

func (u *URN) Equal(x *URN) bool

Equal checks the lexical equivalence of the current URN with another one.

Example
package main

import (
	"fmt"

	"github.com/leodido/go-urn"
)

func main() {
	var uid1 = "URN:foo:a123,456"
	var uid2 = "URN:FOO:a123,456"

	u1, ok := urn.Parse([]byte(uid1))
	if !ok {
		panic("invalid urn")
	}

	u2, ok := urn.Parse([]byte(uid2))
	if !ok {
		panic("invalid urn")
	}

	if u1.Equal(u2) {
		fmt.Printf("%s equals %s", u1.String(), u2.String())
	}

}
Output:
URN:foo:a123,456 equals URN:FOO:a123,456

func (*URN) IsSCIM added in v1.3.0

func (u *URN) IsSCIM() bool

func (URN) MarshalJSON added in v1.2.1

func (u URN) MarshalJSON() ([]byte, error)

MarshalJSON marshals the URN to JSON string form (e.g. `"urn:oid:1.2.3.4"`).

Example
package main

import (
	"fmt"

	"github.com/leodido/go-urn"
)

func main() {
	var uid = "URN:foo:a123,456"

	if u, ok := urn.Parse([]byte(uid)); ok {
		json, err := u.MarshalJSON()
		if err != nil {
			panic("invalid urn")
		}
		fmt.Println(string(json))
	}

}
Output:
"URN:foo:a123,456"

func (*URN) Normalize

func (u *URN) Normalize() *URN

Normalize turns the receiving URN into its norm version.

Which means: lowercase prefix, lowercase namespace identifier, and immutate namespace specific string chars (except <hex> tokens which are lowercased).

func (*URN) SCIM added in v1.3.0

func (u *URN) SCIM() *SCIM

func (*URN) String

func (u *URN) String() string

String reassembles the URN into a valid URN string.

This requires both ID and SS fields to be non-empty. Otherwise it returns an empty string.

Default URN prefix is "urn".

func (*URN) UnmarshalJSON added in v1.2.1

func (u *URN) UnmarshalJSON(bytes []byte) error

UnmarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`).

Directories

Path Synopsis
scim
tools
snake2camel module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL