Commit 98fdaf17 authored by Eric Myhre's avatar Eric Myhre

Fix for empty string PathSegment.

Yep, it makes a lot of creation by struct uglier, as you can see in the
diff to the test file.  Fortunately?  Nobody outside the package is
allowed to do that anyway, so, we can pretty much ignore the ergonomic.
(It'll still look uglier if someone's looking at stuff with spew or
go-cmp or some other library like that which peeks naughtily into
unexported fields, but that's hard to do much about.)

We could also address this by adding a discriminant field to the
PathSegment struct.  (If we wanted to use uint internally, we'd
probably have to do that, in fact.  Either that or start using
some other alarmingly magical number like UINT_MAX.  Ygh.)  I didn't.
I don't think we handle lists larger than 2 billion elements
particularly well anyway... so, adding more words of memory to
PathSegment to support that case seems like an entirely losing trade.
parent 2d590abe
......@@ -51,9 +51,10 @@ type PathSegment struct {
we're using the first tactic.
(We also currently get away with having no extra discriminator bit
because empty string is not considered a valid segment,
because we use a signed int for indexes, and negative values aren't valid there,
and thus we can use it as a sentinel value.
This may change if the IPLD Path spec comes to other conclusions about this.)
(Fun note: Empty strings were originally used for this sentinel,
but it turns out empty strings are valid PathSegment themselves, so!))
*/
s string
......@@ -65,13 +66,13 @@ type PathSegment struct {
// (Note: there is currently no escaping specified for PathSegments,
// so this is currently functionally equivalent to PathSegmentOfString.)
func ParsePathSegment(s string) PathSegment {
return PathSegment{s: s}
return PathSegment{s: s, i: -1}
}
// PathSegmentOfString boxes a string into a PathSegment.
// It does not attempt to parse any escaping; use ParsePathSegment for that.
func PathSegmentOfString(s string) PathSegment {
return PathSegment{s: s}
return PathSegment{s: s, i: -1}
}
// PathSegmentOfString boxes an int into a PathSegment.
......@@ -83,7 +84,7 @@ func PathSegmentOfInt(i int) PathSegment {
// but this is considered an implementation detail that's non-semantic.
// If it returns false, it implicitly means "containsInt", as these are the only options.
func (ps PathSegment) containsString() bool {
return ps.s != ""
return ps.i < 0
}
// String returns the PathSegment as a string.
......
......@@ -8,22 +8,22 @@ import (
func TestParsePath(t *testing.T) {
t.Run("parsing one segment", func(t *testing.T) {
Wish(t, ParsePath("0").segments, ShouldEqual, []PathSegment{{s: "0"}})
Wish(t, ParsePath("0").segments, ShouldEqual, []PathSegment{{s: "0", i: -1}})
})
t.Run("parsing three segments", func(t *testing.T) {
Wish(t, ParsePath("0/foo/2").segments, ShouldEqual, []PathSegment{{s: "0"}, {s: "foo"}, {s: "2"}})
Wish(t, ParsePath("0/foo/2").segments, ShouldEqual, []PathSegment{{s: "0", i: -1}, {s: "foo", i: -1}, {s: "2", i: -1}})
})
t.Run("eliding leading slashes", func(t *testing.T) {
Wish(t, ParsePath("/0/2").segments, ShouldEqual, []PathSegment{{s: "0"}, {s: "2"}})
Wish(t, ParsePath("/0/2").segments, ShouldEqual, []PathSegment{{s: "0", i: -1}, {s: "2", i: -1}})
})
t.Run("eliding trailing", func(t *testing.T) {
Wish(t, ParsePath("0/2/").segments, ShouldEqual, []PathSegment{{s: "0"}, {s: "2"}})
Wish(t, ParsePath("0/2/").segments, ShouldEqual, []PathSegment{{s: "0", i: -1}, {s: "2", i: -1}})
})
t.Run("eliding empty segments", func(t *testing.T) { // NOTE: a spec for string encoding might cause this to change in the future!
Wish(t, ParsePath("0//2").segments, ShouldEqual, []PathSegment{{s: "0"}, {s: "2"}})
Wish(t, ParsePath("0//2").segments, ShouldEqual, []PathSegment{{s: "0", i: -1}, {s: "2", i: -1}})
})
t.Run("escaping segments", func(t *testing.T) { // NOTE: a spec for string encoding might cause this to change in the future!
Wish(t, ParsePath(`0/\//2`).segments, ShouldEqual, []PathSegment{{s: "0"}, {s: `\`}, {s: "2"}})
Wish(t, ParsePath(`0/\//2`).segments, ShouldEqual, []PathSegment{{s: "0", i: -1}, {s: `\`, i: -1}, {s: "2", i: -1}})
})
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment