...

Source file src/github.com/leodido/go-urn/urn.go

Documentation: github.com/leodido/go-urn

     1  package urn
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  )
     8  
     9  const errInvalidURN = "invalid URN: %s"
    10  
    11  // URN represents an Uniform Resource Name.
    12  //
    13  // The general form represented is:
    14  //
    15  //	urn:<id>:<ss>
    16  //
    17  // Details at https://tools.ietf.org/html/rfc2141.
    18  type URN struct {
    19  	prefix     string // Static prefix. Equal to "urn" when empty.
    20  	ID         string // Namespace identifier (NID)
    21  	SS         string // Namespace specific string (NSS)
    22  	norm       string // Normalized namespace specific string
    23  	kind       Kind
    24  	scim       *SCIM
    25  	rComponent string // RFC8141
    26  	qComponent string // RFC8141
    27  	fComponent string // RFC8141
    28  	rStart     bool   // RFC8141
    29  	qStart     bool   // RFC8141
    30  	tolower    []int
    31  }
    32  
    33  // Normalize turns the receiving URN into its norm version.
    34  //
    35  // Which means: lowercase prefix, lowercase namespace identifier, and immutate namespace specific string chars (except <hex> tokens which are lowercased).
    36  func (u *URN) Normalize() *URN {
    37  	return &URN{
    38  		prefix: "urn",
    39  		ID:     strings.ToLower(u.ID),
    40  		SS:     u.norm,
    41  		// rComponent: u.rComponent,
    42  		// qComponent: u.qComponent,
    43  		// fComponent: u.fComponent,
    44  	}
    45  }
    46  
    47  // Equal checks the lexical equivalence of the current URN with another one.
    48  func (u *URN) Equal(x *URN) bool {
    49  	if x == nil {
    50  		return false
    51  	}
    52  	nu := u.Normalize()
    53  	nx := x.Normalize()
    54  
    55  	return nu.prefix == nx.prefix && nu.ID == nx.ID && nu.SS == nx.SS
    56  }
    57  
    58  // String reassembles the URN into a valid URN string.
    59  //
    60  // This requires both ID and SS fields to be non-empty.
    61  // Otherwise it returns an empty string.
    62  //
    63  // Default URN prefix is "urn".
    64  func (u *URN) String() string {
    65  	var res string
    66  	if u.ID != "" && u.SS != "" {
    67  		if u.prefix == "" {
    68  			res += "urn"
    69  		}
    70  		res += u.prefix + ":" + u.ID + ":" + u.SS
    71  		if u.rComponent != "" {
    72  			res += "?+" + u.rComponent
    73  		}
    74  		if u.qComponent != "" {
    75  			res += "?=" + u.qComponent
    76  		}
    77  		if u.fComponent != "" {
    78  			res += "#" + u.fComponent
    79  		}
    80  	}
    81  
    82  	return res
    83  }
    84  
    85  // Parse is responsible to create an URN instance from a byte array matching the correct URN syntax (RFC 2141).
    86  func Parse(u []byte, options ...Option) (*URN, bool) {
    87  	urn, err := NewMachine(options...).Parse(u)
    88  	if err != nil {
    89  		return nil, false
    90  	}
    91  
    92  	return urn, true
    93  }
    94  
    95  // MarshalJSON marshals the URN to JSON string form (e.g. `"urn:oid:1.2.3.4"`).
    96  func (u URN) MarshalJSON() ([]byte, error) {
    97  	return json.Marshal(u.String())
    98  }
    99  
   100  // UnmarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`).
   101  func (u *URN) UnmarshalJSON(bytes []byte) error {
   102  	var str string
   103  	if err := json.Unmarshal(bytes, &str); err != nil {
   104  		return err
   105  	}
   106  	if value, ok := Parse([]byte(str)); !ok {
   107  		return fmt.Errorf(errInvalidURN, str)
   108  	} else {
   109  		*u = *value
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func (u *URN) IsSCIM() bool {
   116  	return u.kind == RFC7643
   117  }
   118  
   119  func (u *URN) SCIM() *SCIM {
   120  	if u.kind != RFC7643 {
   121  		return nil
   122  	}
   123  
   124  	return u.scim
   125  }
   126  
   127  func (u *URN) RFC() Kind {
   128  	return u.kind
   129  }
   130  
   131  func (u *URN) FComponent() string {
   132  	return u.fComponent
   133  }
   134  
   135  func (u *URN) QComponent() string {
   136  	return u.qComponent
   137  }
   138  
   139  func (u *URN) RComponent() string {
   140  	return u.rComponent
   141  }
   142  

View as plain text