blob: be10da22bdbc358db9c78420363c53ccd35cbdb1 [file] [log] [blame]
Nigel Taofcb64162020-07-10 22:49:41 +10001// Copyright 2020 The Wuffs Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// +build ignore
16
17package main
18
19// extract-cbor-rfc-7049-examples.go extracts the examples (Appendix A) from
Nigel Tao1e96ef22020-07-27 22:00:28 +100020// RFC 7049 "Concise Binary Object Representation (CBOR)". If the -concat flag
21// is passed, a single CBOR array containing all of the examples are written to
22// stdout. Otherwise, each example is written to a separate file under a
23// "cbor-rfc-7049-examples" directory.
Nigel Taofcb64162020-07-10 22:49:41 +100024//
25// Usage:
26// go run extract-cbor-rfc-7049-examples.go < rfc7049-errata-corrected.txt
27//
28// The rfc7049-errata-corrected.txt file comes from
29// https://github.com/cbor/spec-with-errata-fixed
Nigel Tao0054a052020-07-24 22:47:39 +100030//
31// In hindsight, it would have been easier to start from
32// https://github.com/cbor/test-vectors
Nigel Taofcb64162020-07-10 22:49:41 +100033
34import (
35 "bytes"
Nigel Tao1e96ef22020-07-27 22:00:28 +100036 "flag"
Nigel Taofcb64162020-07-10 22:49:41 +100037 "fmt"
38 "io/ioutil"
39 "os"
40)
41
Nigel Tao1e96ef22020-07-27 22:00:28 +100042var concat = flag.Bool("concat", false, "output one monolithic CBOR file")
43
Nigel Taofcb64162020-07-10 22:49:41 +100044func main() {
45 if err := main1(); err != nil {
46 os.Stderr.WriteString(err.Error() + "\n")
47 os.Exit(1)
48 }
49}
50
51func main1() error {
52 src, err := readExampleTable()
53 if err != nil {
54 return err
55 }
Nigel Tao1e96ef22020-07-27 22:00:28 +100056 if *concat {
57 // Start of CBOR indefinite-length array.
58 os.Stdout.Write([]byte("\x9F"))
59 } else if err := os.Mkdir("cbor-rfc-7049-examples", 0755); err != nil {
Nigel Taofcb64162020-07-10 22:49:41 +100060 return err
61 }
62 for remaining := []byte(nil); len(src) > 0; src = remaining {
63 if i := bytes.IndexByte(src, '\n'); i >= 0 {
64 src, remaining = src[:i], src[i+1:]
65 } else {
66 remaining = nil
67 }
68 src = bytes.TrimSpace(src)
69 if (len(src) == 0) || (src[0] != '|') {
70 continue
71 }
72 if (len(src) != 69) || (src[31] != '|') || (src[68] != '|') {
73 return fmt.Errorf("main: unexpected table row: %q", string(src))
74 }
75 src = bytes.TrimSpace(src[33:68])
76 if len(src) == 0 {
77 if err := emit(); err != nil {
78 return err
79 }
80 continue
81 }
82 if (len(src) > 1) && (src[0] == '0') && (src[1] == 'x') {
83 src = src[2:]
84 }
85 for ; len(src) >= 2; src = src[2:] {
86 contents = append(contents, (unhex(src[0])<<4)|unhex(src[1]))
87 }
88 }
Nigel Tao1e96ef22020-07-27 22:00:28 +100089 if err := emit(); err != nil {
90 return err
91 }
92 if *concat {
93 // End of CBOR indefinite-length array.
94 os.Stdout.Write([]byte("\xFF"))
95 }
96 return nil
Nigel Taofcb64162020-07-10 22:49:41 +100097}
98
99var (
100 contents = []byte(nil)
101 fileNumber = 0
102)
103
104func emit() error {
105 if len(contents) == 0 {
106 return nil
107 }
Nigel Tao1e96ef22020-07-27 22:00:28 +1000108 if *concat {
109 os.Stdout.Write(contents)
110 contents = nil
111 return nil
112 }
Nigel Taofcb64162020-07-10 22:49:41 +1000113 filename := fmt.Sprintf("cbor-rfc-7049-examples/%02d.cbor", fileNumber)
114 fileNumber++
115 err := ioutil.WriteFile(filename, contents, 0644)
116 contents = nil
117 return err
118}
119
120func unhex(x uint8) uint8 {
121 if x >= 'a' {
122 return x + 10 - 'a'
123 }
124 return x - '0'
125}
126
127func readExampleTable() ([]byte, error) {
128 appendixA := []byte("Appendix A. Examples\n\n")
129 ruler := []byte("+------------------------------+------------------------------------+\n")
130
131 src, err := ioutil.ReadAll(os.Stdin)
132 if err != nil {
133 return nil, err
134 }
135 if i := bytes.Index(src, appendixA); i < 0 {
136 return nil, fmt.Errorf("main: couldn't find Appendix A")
137 } else {
138 src = src[i+len(appendixA):]
139 }
140 if i := bytes.Index(src, ruler); i < 0 {
141 return nil, fmt.Errorf("main: couldn't find ---- ruler")
142 } else {
143 src = src[i+len(ruler):]
144 }
145 if i := bytes.Index(src, ruler); i < 0 {
146 return nil, fmt.Errorf("main: couldn't find ---- ruler")
147 } else {
148 src = src[i+len(ruler):]
149 }
150 if i := bytes.Index(src, ruler); i < 0 {
151 return nil, fmt.Errorf("main: couldn't find Appendix B")
152 } else {
153 src = src[:i]
154 }
155 return bytes.TrimSpace(src), nil
156}