/* Reads and returns the next DER encoded SEQUENCE from r, which may optionally be base64 encoded and may be preceded by "garbage". The returned data will always be DER bytes without preceding garbage and NOT base64 encoded. The SEQUENCE will only be recognized as valid if it does not contain APPLICATION or PRIVATE tags or tags >= 31. This function takes care not to read more bytes than necessary which allows the function to be called multiple times on a stream of concatenated SEQUENCEs. */ func ReadNextSEQUENCE(r io.Reader) ([]byte, error) { b := []byte{0} var err error var n int space := true var eaters deque.Deque for { n, err = r.Read(b) if err != nil { return nil, err } if n == 0 { return nil, io.EOF } if b[0] == 0x30 { // SEQUENCE eaters.Push(newRawEater()) } if b[0] > ' ' { if space { eaters.Push(newBase64Eater()) } space = false } else { space = true } for i := 0; i < eaters.Count(); { result := eaters.At(i).(eater).Eat(b[0]) switch result { case -1: // error eaters.RemoveAt(i) case 0: // ok, need more data i++ case 1: // done return eaters.At(i).(eater).Data(), nil } } } }
func Deque(deck *deque.Deque, data ...interface{}) string { deck.CheckInvariant() if deck.Count() != len(data) { return fmt.Sprintf("Count() is %v but should be %v", deck.Count(), len(data)) } if deck.IsEmpty() != (len(data) == 0) { return fmt.Sprintf("IsEmpty() should be %v", (len(data) == 0)) } if deck.IsFull() != (len(data) == deck.Capacity()) { return fmt.Sprintf("IsFull() should be %v", (len(data) == deck.Capacity())) } for i := range data { if deck.At(i) != data[i] { return fmt.Sprintf("At(%v) is %v but should be %v", i, deck.At(i), data[i]) } if deck.Peek(i) != data[len(data)-1-i] { return fmt.Sprintf("Peek(%v) is %v but should be %v", i, deck.Peek(i), data[len(data)-1-i]) } p := deck.Put(i, "x") if p != data[i] { return fmt.Sprintf("Put(%v,x) is %v but should be %v", i, p, data[i]) } if deck.Put(i, p).(string) != "x" { return fmt.Sprintf("Put is broken") } p = deck.Poke(i, "x") if p != data[len(data)-1-i] { return fmt.Sprintf("Poke(%v,x) is %v but should be %v", i, p, data[len(data)-1-i]) } if deck.Poke(i, p).(string) != "x" { return fmt.Sprintf("Poke is broken") } if deck.At(i) != data[i] { return fmt.Sprintf("After Put/Poke At(%v) is %v but should be %v", i, deck.At(i), data[i]) } if deck.Peek(i) != data[len(data)-1-i] { return fmt.Sprintf("After Put/Poke Peek(%v) is %v but should be %v", i, deck.Peek(i), data[len(data)-1-i]) } } var zero interface{} if deck.Peek(-1) != zero { return fmt.Sprintf("Peek(-1) returns %v", deck.Peek(-1)) } if deck.Peek(-1) != nil { return fmt.Sprintf("Peek(-1) returns %v", deck.Peek(-1)) } if deck.Poke(-1, "foo") != zero { return fmt.Sprintf("Poke(-1,foo) returns not nil") } if deck.Poke(-1, "foo") != nil { return fmt.Sprintf("Poke(-1,foo) returns not nil") } if deck.At(-1) != zero { return fmt.Sprintf("At(-1) returns %v", deck.At(-1)) } if deck.At(-1) != nil { return fmt.Sprintf("At(-1) returns %v", deck.At(-1)) } if deck.Put(-1, "foo") != zero { return fmt.Sprintf("Put(-1,foo) returns not nil") } if deck.Put(-1, "foo") != nil { return fmt.Sprintf("Put(-1,foo) returns not nil") } if deck.Peek(len(data)) != zero { return fmt.Sprintf("Peek(len(data)) returns %v", deck.Peek(len(data))) } if deck.Peek(len(data)) != nil { return fmt.Sprintf("Peek(len(data)) returns %v", deck.Peek(len(data))) } if deck.Poke(len(data), "foo") != zero { return fmt.Sprintf("Poke(len(data),foo) returns not nil") } if deck.Poke(len(data), "foo") != nil { return fmt.Sprintf("Poke(len(data),foo) returns not nil") } if deck.At(len(data)) != zero { return fmt.Sprintf("At(len(data)) returns %v", deck.At(len(data))) } if deck.At(len(data)) != nil { return fmt.Sprintf("At(len(data)) returns %v", deck.At(len(data))) } if deck.Put(len(data), "foo") != zero { return fmt.Sprintf("Put(len(data),foo) returns not nil") } if deck.Put(len(data), "foo") != nil { return fmt.Sprintf("Put(len(data),foo) returns not nil") } if deck.String() != "Deque"+fmt.Sprintf("%v", data) { return fmt.Sprintf("String() returns \"%v\" instead of \"%v\"", deck.String(), "Deque"+fmt.Sprintf("%v", data)) } return "" }