urn

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Jan 31, 2024 License: MIT Imports: 4 Imported by: 140

README

Build Coverage Documentation

A parser for URNs.

As seen on RFC 2141, RFC 7643, and on RFC 8141.

API documentation.

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

Starting with version 1.4 this library also supports RFC 8141 URNs (2017).

Installation

go get github.com/leodido/go-urn

Features

  1. RFC 2141 URNs parsing (default)
  2. RFC 8141 URNs parsing (supersedes RFC 2141)
  3. RFC 7643 SCIM URNs parsing
  4. Normalization as per RFCs
  5. Lexical equivalence as per RFCs
  6. Precise, fine-grained errors

Performances

This implementation results to be really fast.

Usually below 400 ns on my machine1.

Notice it also performs, while parsing:

  1. fine-grained and informative erroring
  2. specific-string normalization
ok/00/urn:a:b______________________________________/-10    51372006    109.0 ns/op    275 B/op    3 allocs/op
ok/01/URN:foo:a123,456_____________________________/-10    36024072    160.8 ns/op    296 B/op    6 allocs/op
ok/02/urn:foo:a123%2C456___________________________/-10    31901007    188.4 ns/op    320 B/op    7 allocs/op
ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-10    22736756    266.6 ns/op    376 B/op    6 allocs/op
ok/04/urn:ietf:params:scim:schemas:extension:enterp/-10    18291859    335.2 ns/op    408 B/op    6 allocs/op
ok/05/urn:ietf:params:scim:schemas:extension:enterp/-10    15283087    379.4 ns/op    440 B/op    6 allocs/op
ok/06/urn:burnout:nss______________________________/-10    39407593    155.1 ns/op    288 B/op    6 allocs/op
ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-10    27832718    211.4 ns/op    307 B/op    4 allocs/op
ok/08/urn:urnurnurn:urn____________________________/-10    33269596    168.1 ns/op    293 B/op    6 allocs/op
ok/09/urn:ciao:!!*_________________________________/-10    41100675    148.8 ns/op    288 B/op    6 allocs/op
ok/10/urn:ciao:=@__________________________________/-10    37214253    149.7 ns/op    284 B/op    6 allocs/op
ok/11/urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'_____________/-10    26534240    229.8 ns/op    336 B/op    7 allocs/op
ok/12/URN:x:abc%1Dz%2F%3az_________________________/-10    28166396    211.8 ns/op    336 B/op    7 allocs/op
no/13/URN:---xxx:x_________________________________/-10    23635159    255.6 ns/op    419 B/op    5 allocs/op
no/14/urn::colon:nss_______________________________/-10    23594779    258.4 ns/op    419 B/op    5 allocs/op
no/15/URN:@,:x_____________________________________/-10    23742535    261.5 ns/op    419 B/op    5 allocs/op
no/16/URN:URN:NSS__________________________________/-10    27432714    223.3 ns/op    371 B/op    5 allocs/op
no/17/urn:UrN:NSS__________________________________/-10    26922117    224.9 ns/op    371 B/op    5 allocs/op
no/18/urn:a:%______________________________________/-10    24926733    224.6 ns/op    371 B/op    5 allocs/op
no/19/urn:urn:NSS__________________________________/-10    27652641    220.7 ns/op    371 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
	RFC8141
)

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 (
	Default ParsingMode = iota
	RFC2141Only
	RFC7643Only
	RFC8141Only
)

type SCIM added in v1.3.0

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

func (SCIM) MarshalJSON added in v1.4.0

func (s SCIM) MarshalJSON() ([]byte, error)

func (*SCIM) String added in v1.4.0

func (s *SCIM) String() string

func (*SCIM) UnmarshalJSON added in v1.4.0

func (s *SCIM) UnmarshalJSON(bytes []byte) error

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
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)
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
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) FComponent added in v1.4.0

func (u *URN) FComponent() string

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
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) QComponent added in v1.4.0

func (u *URN) QComponent() string

func (*URN) RComponent added in v1.4.0

func (u *URN) RComponent() string

func (*URN) RFC added in v1.4.0

func (u *URN) RFC() Kind

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"`).

type URN8141 added in v1.4.0

type URN8141 struct {
	*URN
}

func (URN8141) MarshalJSON added in v1.4.0

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

func (*URN8141) UnmarshalJSON added in v1.4.0

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

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