id

package
Version: v0.0.0-...-0d16973 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2021 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package id describes C4's dot-delimited IDs.

Index

Examples

Constants

View Source
const (
	// ArchFamilyC is the tag representing the C pseudo-architecture family.
	ArchFamilyC = "c"

	// ArchFamilyX86 is the tag representing the X86 architecture family.
	ArchFamilyX86 = "x86"
	// ArchFamilyArm is the tag representing the 32-bit Arm architecture family.
	ArchFamilyArm = "arm"
	// ArchFamilyAArch64 is the tag representing the 64-bit Arm architecture family.
	ArchFamilyAArch64 = "aarch64"
	// ArchFamilyPPC is the tag representing the PowerPC architecture family.
	ArchFamilyPPC = "ppc"

	// ArchVariantArm7 is the tag representing the arm7(-a) Arm variant.
	ArchVariantArm7 = "7"
	// ArchVariantArm8 is the tag representing the arm8(-a) Arm variant.
	ArchVariantArm8 = "8"
	// ArchVariantArmCortexA72 is the tag representing the Cortex-A72 Arm variant.
	// This variant is, for example, that used on the Raspberry Pi 4.
	ArchVariantArmCortexA72 = "cortex-a72"

	// ArchVariantAArch648 is the tag representing the arm8.x(-a) AArch64 variant.
	ArchVariantAArch648 = "8"

	// ArchSubVariantAArch6481 is the tag representing the arm8.1(-a) AArch64 variant.
	ArchSubVariantAArch6481 = "1"

	// ArchVariantPPC64LE is the tag representing the 64-bit little-endian PPC variant.
	ArchVariantPPC64LE = "64le"

	// ArchSubVariantPPCPOWER7 is the tag representing the POWER7 PPC sub-variant.
	ArchSubVariantPPCPOWER7 = "power7"
	// ArchSubVariantPPCPOWER8 is the tag representing the POWER8 PPC sub-variant.
	ArchSubVariantPPCPOWER8 = "power8"
	// ArchSubVariantPPCPOWER9 is the tag representing the POWER9 PPC sub-variant.
	ArchSubVariantPPCPOWER9 = "power9"

	// ArchVariantX8664 is the tag representing the 64-bit x86 variant.
	ArchVariantX8664 = "64"

	// ArchSubVariantX86Broadwell is the tag representing the Intel Broadwell x86-64 subvariant.
	ArchSubVariantX86Broadwell = "broadwell"
	// ArchSubVariantX86Skylake is the tag representing the Intel Skylake x86-64 subvariant.
	// This variant is, for example, that used in 2016 MacBook Pros.
	ArchSubVariantX86Skylake = "skylake"
)
View Source
const (
	// SepTag is the identifier tag separator.
	// It is exported for testing and sanitisation purposes.
	SepTag = "."
)
View Source
const TagGlob = "*"

TagGlob is the tag used in a glob expression to indicate that everything before it should be a prefix, and everything after a suffix, of the matched ID.

Variables

View Source
var (
	// ErrTagHasSep occurs when a tag passed to New contains the separator rune.
	ErrTagHasSep = errors.New("tag contains separator")

	// ErrTagEmpty occurs when a tag passed to New is empty.
	ErrTagEmpty = errors.New("tag empty")
)
View Source
var (
	// ArchC is the architecture ID for C.
	// (C isn't an architecture, but certain parts of the backend system are easier if we treat it as one.)
	ArchC = ID{/* contains filtered or unexported fields */}

	// ArchX86 is the architecture ID for x86 (generic, assumed 32-bit).
	ArchX86 = ID{/* contains filtered or unexported fields */}
	// ArchX8664 is the architecture ID for x86-64.
	ArchX8664 = ID{/* contains filtered or unexported fields */}
	// ArchX86Broadwell is the architecture ID for x86-64 Broadwell.
	ArchX86Broadwell = ID{/* contains filtered or unexported fields */}
	// ArchX86Skylake is the architecture ID for x86-64 Skylake.
	ArchX86Skylake = ID{/* contains filtered or unexported fields */}

	// ArchArm is the architecture ID for ARM (generic, 32-bit).
	ArchArm = ID{/* contains filtered or unexported fields */}
	// ArchArm7 is the architecture ID for arm7(-a).
	ArchArm7 = ID{/* contains filtered or unexported fields */}
	// ArchArm8 is the architecture ID for arm8(-a).
	ArchArm8 = ID{/* contains filtered or unexported fields */}
	// ArchArmCortexA72 is the architecture ID for arm Cortex-A72.
	ArchArmCortexA72 = ID{/* contains filtered or unexported fields */}

	// ArchAArch64 is the architecture ID for ARM (generic, 64-bit).
	ArchAArch64 = ID{/* contains filtered or unexported fields */}
	// ArchAArch648 is the architecture ID for ARM 64-bit version 8.x.
	ArchAArch648 = ID{/* contains filtered or unexported fields */}
	// ArchAArch6481 is the architecture ID for ARM 64-bit version 8.1.
	ArchAArch6481 = ID{/* contains filtered or unexported fields */}

	// ArchPPC is the architecture ID for PowerPC.
	ArchPPC = ID{/* contains filtered or unexported fields */}
	// ArchPPC64LE is the architecture ID for PowerPC64LE.
	ArchPPC64LE = ID{/* contains filtered or unexported fields */}
	// ArchPPCPOWER7 is the architecture ID for POWER7.
	ArchPPCPOWER7 = ID{/* contains filtered or unexported fields */}
	// ArchPPCPOWER8 is the architecture ID for POWER8.
	ArchPPCPOWER8 = ID{/* contains filtered or unexported fields */}
	// ArchPPCPOWER9 is the architecture ID for POWER9.
	ArchPPCPOWER9 = ID{/* contains filtered or unexported fields */}

	// CStyleGCC is the compiler style ID for GCC.
	CStyleGCC = ID{/* contains filtered or unexported fields */}
)
View Source
var ErrBadGlob = errors.New("malformed glob expression")

ErrBadGlob occurs when Matches gets a malformed glob expression.

View Source
var ErrNotMap = errors.New("not a map with ID keys")

ErrNotMap occurs when we try to use an ID map function on something that isn't an ID map.

Functions

func MapGlob

func MapGlob(m interface{}, glob ID) (interface{}, error)

MapGlob filters a string map m to those keys that match glob when interpreted as IDs.

Example

ExampleMapGlob is a runnable example for MapGlob.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	c := map[id.ID]int{
		id.FromString("foo.baz"):     1,
		id.FromString("foo.bar.baz"): 2,
		id.FromString("foo.bar"):     3,
		id.FromString("bar.baz"):     4,
	}
	c2, _ := id.MapGlob(c, id.FromString("foo.*.baz"))
	for k, v := range c2.(map[id.ID]int) {
		fmt.Println(k, v)
	}

}
Output:

foo.baz 1
foo.bar.baz 2

func SearchSlice

func SearchSlice(haystack []ID, needle ID) int

SearchSlice finds the smallest index in haystack for which the ID at that index is greater than or equal to needle. If there is no such index, it returns len(haystack).

Example

ExampleSearchSlice is a runnable example for SearchSlice.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	haystack := []id.ID{
		id.FromString("fus"),
		id.FromString("fus.ro"),
		id.FromString("fus.ro.dah"),
	}

	fmt.Println(id.SearchSlice(haystack, id.ID{}))
	fmt.Println(id.SearchSlice(haystack, id.FromString("fus.dah")))
	fmt.Println(id.SearchSlice(haystack, id.FromString("fus.ro.dah")))
	fmt.Println(id.SearchSlice(haystack, id.FromString("fus.ro.dah.dah.dah")))

}
Output:

0
1
2
3

func Sort

func Sort(ids []ID)

Sort sorts ids.

Example

ExampleSort is a runnable example for Sort.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	ids := []id.ID{
		id.FromString("arm.7"),
		id.FromString("arm.8"),
		id.FromString("ppc.64.le"),
		id.FromString("x86.32"),
		id.FromString("x86"),
		id.FromString("arm"),
		id.FromString("ppc"),
		id.FromString("x86.64"),
		id.FromString("ppc.64"),
		id.FromString("arm.6"),
	}
	id.Sort(ids)
	for _, i := range ids {
		fmt.Println(i)
	}

}
Output:

arm
arm.6
arm.7
arm.8
ppc
ppc.64
ppc.64.le
x86
x86.32
x86.64

Types

type ID

type ID struct {
	// contains filtered or unexported fields
}

ID represents a C4 ID.

func FromString

func FromString(s string) ID

FromString converts a string to a C4 ID. It returns the empty ID if there is an error.

Example

ExampleFromString is a runnable example for FromString.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	fmt.Println(id.FromString("foo.bar.baz"))
	fmt.Println(id.FromString("FOO.BAR.BAZ"))
	fmt.Println(id.FromString("foo..bar.baz"))

}
Output:

foo.bar.baz
foo.bar.baz

func LookupPrefix

func LookupPrefix(m interface{}, id ID) (key ID, val interface{}, ok bool)

LookupPrefix looks up id in map m by starting from the id itself, progressively taking a smaller and smaller prefix up to and including the empty ID, and returning the first value found. If a lookup succeeded, LookupPrefix returns the matched key as key, the value as val, and true as ok; else, it returns false, and the other two values are undefined.

Example

ExampleLookupPrefix is a runnable example for LookupPrefix.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	c := map[id.ID]int{
		id.ID{}:                  0,
		id.FromString("foo"):     1,
		id.FromString("bar"):     2,
		id.FromString("bar.baz"): 3,
	}

	k1, v1, _ := id.LookupPrefix(c, id.FromString("bar.baz"))
	k2, v2, _ := id.LookupPrefix(c, id.FromString("bar.foobaz"))
	k3, v3, _ := id.LookupPrefix(c, id.FromString("foo.bar.baz"))
	k4, v4, _ := id.LookupPrefix(c, id.FromString("baz"))

	fmt.Printf("matched bar.baz to %q (%d)\n", k1, v1)
	fmt.Printf("matched bar.foobaz to %q (%d)\n", k2, v2)
	fmt.Printf("matched foo.bar.baz to %q (%d)\n", k3, v3)
	fmt.Printf("matched baz to %q (%d)\n", k4, v4)

}
Output:

matched bar.baz to "bar.baz" (3)
matched bar.foobaz to "bar" (2)
matched foo.bar.baz to "foo" (1)
matched baz to "" (0)

func MapKeys

func MapKeys(m interface{}) ([]ID, error)

MapKeys tries to get the keys of an ID-as-string map m as a sorted list. It fails if m is not an ID-as-string map.

Example

ExampleMapKeys is a runnable example for MapKeys.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	c := map[id.ID]int{
		id.FromString("foo.bar"):       1,
		id.FromString("BAR"):           2,
		id.FromString("foobar.baz"):    3,
		id.FromString("barbaz.Foobaz"): 4,
	}
	ids, _ := id.MapKeys(c)
	for _, x := range ids {
		fmt.Println(x)
	}

}
Output:

bar
barbaz.foobaz
foo.bar
foobar.baz

func New

func New(tags ...string) (ID, error)

New tries to construct a C4 ID from tags. It fails if any of the tags is empty (unless there is only one such tag), or contains a separator.

func TryFromString

func TryFromString(s string) (ID, error)

TryFromString tries to convert a string to a C4 ID. It returns any validation error arising.

func (ID) Equal

func (i ID) Equal(i2 ID) bool

Equal compares two IDs for equality.

Example

ExampleID_Less is a runnable example for Equal.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	fmt.Println(id.FromString("arm.7").Equal(id.FromString("arm.7")))
	fmt.Println(id.FromString("arm.7").Equal(id.FromString("arm.8")))
	fmt.Println(id.FromString("arm.7").Equal(id.FromString("ARM.8")))
	fmt.Println(id.FromString("arm.7").Equal(id.FromString("arm")))
	fmt.Println(id.ID{}.Equal(id.FromString("")))

}
Output:

true
false
false
false
true

func (ID) HasPrefix

func (i ID) HasPrefix(prefix ID) bool

HasPrefix tests whether prefix is a prefix of this ID.

Example

ExampleID_HasPrefix is a runnable example for HasPrefix.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	x := id.FromString("x86.64")
	fmt.Println("x86.64 prefix of x86.64:", x.HasPrefix(id.FromString("x86.64")))
	fmt.Println("x86 prefix of x86.64:", x.HasPrefix(id.FromString("x86")))
	fmt.Println("arm prefix of x86.64:", x.HasPrefix(id.FromString("arm")))
	fmt.Println("empty prefix of x86.64:", x.HasPrefix(id.ID{}))

}
Output:

x86.64 prefix of x86.64: true
x86 prefix of x86.64: true
arm prefix of x86.64: false
empty prefix of x86.64: true

func (ID) HasSuffix

func (i ID) HasSuffix(suffix ID) bool

HasSuffix tests whether suffix is a suffix of this ID.

Example

ExampleID_HasSuffix is a runnable example for HasSuffix.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	x := id.FromString("x86.64")
	fmt.Println("x86.64 suffix of x86.64:", x.HasSuffix(id.FromString("x86.64")))
	fmt.Println("64 suffix of x86.64:", x.HasSuffix(id.FromString("64")))
	fmt.Println("32 suffix of x86.64:", x.HasSuffix(id.FromString("32")))
	fmt.Println("empty suffix of x86.64:", x.HasSuffix(id.ID{}))

}
Output:

x86.64 suffix of x86.64: true
64 suffix of x86.64: true
32 suffix of x86.64: false
empty suffix of x86.64: true

func (ID) IsEmpty

func (i ID) IsEmpty() bool

IsEmpty gets whether this ID is empty.

Example

ExampleID_IsEmpty is a runnable example for IsEmpty.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	fmt.Println(id.ID{}.IsEmpty())
	fmt.Println(id.FromString("").IsEmpty())
	fmt.Println(id.FromString("foo.bar.baz").IsEmpty())

}
Output:

true
true
false

func (ID) Join

func (i ID) Join(r ID) ID

Join appends r to this ID, creating a new ID.

Example

ExampleID_Join is a runnable example for Join.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	id1 := id.FromString("foo.bar")
	id2 := id.FromString("baz.barbaz")
	fmt.Println(id1.Join(id2).String())

	// empty IDs do nothing when joined
	fmt.Println(id.ID{}.Join(id1).String())
	fmt.Println(id2.Join(id.ID{}).String())

}
Output:

foo.bar.baz.barbaz
foo.bar
baz.barbaz

func (ID) Less

func (i ID) Less(i2 ID) bool

Less compares two IDs lexicographically.

Example

ExampleID_Less is a runnable example for Less.

package main

import (
	"fmt"
	"sort"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	ids := []id.ID{
		id.FromString("arm.7"),
		id.FromString("arm.8"),
		id.FromString("ppc.64.le"),
		id.FromString("x86.32"),
		id.FromString("x86"),
		id.FromString("arm"),
		id.FromString("ppc"),
		id.FromString("x86.64"),
		id.FromString("ppc.64"),
		id.FromString("arm.6"),
	}
	// Note: in general, use id.Sort instead!
	sort.Slice(ids, func(i, j int) bool {
		return ids[i].Less(ids[j])
	})
	for _, i := range ids {
		fmt.Println(i)
	}

}
Output:

arm
arm.6
arm.7
arm.8
ppc
ppc.64
ppc.64.le
x86
x86.32
x86.64

func (ID) MarshalText

func (i ID) MarshalText() ([]byte, error)

MarshalText implements text marshalling for IDs by stringifying them.

func (ID) Matches

func (i ID) Matches(glob ID) (bool, error)

Matches tests whether this ID matches the glob ID expression glob. glob should be either a literal ID, or an ID with exactly one tag equal to TagGlob.

func (*ID) Set

func (i *ID) Set(value string) error

Set behaves like TryFromString, but replaces an ID in-place.

func (ID) String

func (i ID) String() string

String converts a C4 ID to a string.

func (ID) Tags

func (i ID) Tags() []string

Tags extracts the tags comprising an ID as a slice.

Example

ExampleID_Tags is a runnable example for Tags.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	for _, tag := range id.FromString("foo.bar.baz").Tags() {
		fmt.Println(tag)
	}

}
Output:

foo
bar
baz

func (ID) Triple

func (i ID) Triple() (f, v string, s ID)

Triple splits this ID into three parts: a family tag, a variant tag, and a subvariant identifier.

Example

ExampleID_Triple is a runnable example for Triple.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	f, v, s := id.ID{}.Triple()
	fmt.Printf("empty ID: f=%q v=%q s=%q\n", f, v, s)

	f, v, s = id.FromString("x86").Triple()
	fmt.Printf("family ID: f=%q v=%q s=%q\n", f, v, s)

	f, v, s = id.FromString("x86.64").Triple()
	fmt.Printf("variant ID: f=%q v=%q s=%q\n", f, v, s)

	f, v, s = id.FromString("x86.64.coffeelake").Triple()
	fmt.Printf("subvariant ID: f=%q v=%q s=%q\n", f, v, s)

}
Output:

empty ID: f="" v="" s=""
family ID: f="x86" v="" s=""
variant ID: f="x86" v="64" s=""
subvariant ID: f="x86" v="64" s="coffeelake"

func (ID) Uncons

func (i ID) Uncons() (hd string, tl ID, ok bool)

Uncons splits an ID into a head tag and tail of zero or more further tags. If the ID is empty, ok is false, and hd and tl are unspecified.

Example

ExampleID_Uncons is a runnable example for Uncons.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	_, _, ok := id.ID{}.Uncons()
	fmt.Println("uncons of empty ok?:", ok)

	// An uncons of a 1-tag ID returns that tag as the head.
	hd, tl, ok := id.FromString("foo").Uncons()
	fmt.Printf("foo: ok=%v, head=%q, tail=%q\n", ok, hd, tl)

	hd, tl, ok = id.FromString("foo.bar.baz").Uncons()
	fmt.Printf("foo.bar.baz: ok=%v, head=%q, tail=%q\n", ok, hd, tl)

}
Output:

uncons of empty ok?: false
foo: ok=true, head="foo", tail=""
foo.bar.baz: ok=true, head="foo", tail="bar.baz"

func (*ID) UnmarshalText

func (i *ID) UnmarshalText(b []byte) error

UnmarshalText implements text unmarshalling for IDs by unstringifying them.

func (ID) Unsnoc

func (i ID) Unsnoc() (hd ID, tl string, ok bool)

Unsnoc splits an ID into a tail tag and head of zero or more preceding tags. If the ID is empty, ok is false, and hd and tl are unspecified.

Example

ExampleID_Unsnoc is a runnable example for Unsnoc.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/id"
)

func main() {
	_, _, ok := id.ID{}.Unsnoc()
	fmt.Println("unsnoc of empty ok?:", ok)

	// An unsnoc of a 1-tag ID returns that tag as the tail.
	hd, tl, ok := id.FromString("foo").Unsnoc()
	fmt.Printf("foo: ok=%v, head=%q, tail=%q\n", ok, hd, tl)

	hd, tl, ok = id.FromString("foo.bar.baz").Unsnoc()
	fmt.Printf("foo.bar.baz: ok=%v, head=%q, tail=%q\n", ok, hd, tl)

}
Output:

unsnoc of empty ok?: false
foo: ok=true, head="", tail="foo"
foo.bar.baz: ok=true, head="foo.bar", tail="baz"

Jump to

Keyboard shortcuts

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