1package doc23import (4 "fmt"5 "hash/fnv"6)78// IDSpace mints the numeric identities a source without its own has to publish.9//10// The document's identifiers are signed 32-bit on the wire and zero reads as11// absence (see the package comment), so a source whose captures name things by12// string has to turn those names into numbers. The rule from ยง1.4 of13// docs/generate.md, made mechanical here:14//15// - The number is a pure function of the name. The same capture numbers16// itself the same way on any machine, in any run, forever, which is what17// lets a reader's hide set and a merge ledger survive a rebuild.18// - The name is the source's own stable spelling of the thing, qualified by19// what it is -- a world, a collection, a feature -- so two kinds of thing20// with one name do not meet.21// - A collision is fatal. Two names landing on one number would silently22// merge two features and lose one, and at this scale a collision means23// something is wrong rather than that the space is full.24//25// An IDSpace is one document's worth of claims. It is not safe for concurrent26// use, and it is not meant to be: a translation is one pass over one volume.27type IDSpace struct {28 claimed map[int64]string29}3031// NewIDSpace opens an empty space.32func NewIDSpace() *IDSpace {33 return &IDSpace{claimed: make(map[int64]string)}34}3536// Claim mints the identity of one named thing, or reports the collision.37func (s *IDSpace) Claim(name string) (int64, error) {38 hash := fnv.New32a()39 _, _ = hash.Write([]byte(name))40 id := int64(hash.Sum32() & 0x7fffffff)41 // Zero is absence on the wire, so nothing may be numbered with it.42 if id == 0 {43 id = 144 }45 // Even the same name twice is refused: a source claiming one thing twice46 // has lost track of what it is describing, and the second claim would have47 // overwritten the first wherever the number is used as a key.48 if holder, taken := s.claimed[id]; taken {49 return 0, fmt.Errorf("%q and %q both number %d", holder, name, id)50 }51 s.claimed[id] = name52 return id, nil53}