Start of a schema library for camput.

This commit is contained in:
Brad Fitzpatrick 2010-12-30 10:17:47 -08:00
parent 5ea7504c84
commit eb60cd6f71
6 changed files with 130 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import (
"camli/blobref"
"camli/clientconfig"
"camli/http"
"camli/schema"
"crypto/sha1"
"encoding/base64"
"flag"
@ -224,6 +225,13 @@ func (a *Agent) UploadFile(filename string) (*PutResult, os.Error) {
if err != nil {
return nil, err
}
fmap, err := schema.NewFileMap(filename)
if err != nil {
return nil, err
}
fmt.Printf("map: %q\n", fmap)
fmt.Println("Got blobref for file blob: ", blobpr.BlobRef.String())
return nil, nil
}

View File

@ -3,6 +3,7 @@ Camli Blob Magic
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
[Note: not totally happy with this yet...]
Ideal Camli JSON blobs should begin with the following 15 bytes:
{"camliVersion"
@ -11,4 +12,15 @@ However, it's acknowledged that some JSON serialization libraries will
format things differently, so additional whitespace should be
tolerated.
An ideal camli serializer will strive for the above header, though, by
doing something like:
-- removing the "camliVersion" from the object, noting its value
(and requiring it to be present)
-- serializing the JSON with an existing JSON serialization library,
-- removing the serialized JSON's leading "{" character and prepending
the 15 byte header above, as well as the colon and saved version
and comma (which can have whitespace as desired)

3
lib/go/schema/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
_test*
*.out
*.[865]

7
lib/go/schema/Makefile Normal file
View File

@ -0,0 +1,7 @@
include $(GOROOT)/src/Make.inc
TARG=camli/schema
GOFILES=\
schema.go\
include $(GOROOT)/src/Make.pkg

58
lib/go/schema/schema.go Normal file
View File

@ -0,0 +1,58 @@
package schema
import (
"bytes"
"fmt"
"json"
"os"
"strings"
)
func isValidUtf8(s string) bool {
for _, rune := range []int(s) {
if rune == 0xfffd {
return false
}
}
return true
}
var NoCamliVersionErr = os.NewError("No camliVersion key in map")
func MapToCamliJson(m map[string]interface{}) (string, os.Error) {
version, hasVersion := m["camliVersion"]
if !hasVersion {
return "", NoCamliVersionErr
}
m["camliVersion"] = 0, false
jsonBytes, err := json.MarshalIndent(m, "", " ")
if err != nil {
return "", err
}
m["camliVersion"] = version
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "{\"camliVersion\": %v,\n", version)
buf.Write(jsonBytes[2:])
return string(buf.Bytes()), nil
}
func NewMapForFileName(fileName string) map[string]interface{} {
ret := make(map[string]interface{})
ret["camliVersion"] = 1
ret["camliType"] = "" // undefined at this point
lastSlash := strings.LastIndex(fileName, "/")
baseName := fileName[lastSlash+1:]
if isValidUtf8(baseName) {
ret["fileName"] = baseName
} else {
ret["fileNameBytes"] = []uint8(baseName)
}
return ret
}
func NewFileMap(fileName string) (map[string]interface{}, os.Error) {
ret := NewMapForFileName(fileName)
// TODO: ...
return ret, nil
}

View File

@ -0,0 +1,42 @@
package schema
import (
"strings"
"testing"
)
type isUtf8Test struct {
s string
e bool
}
func TestIsUtf8(t *testing.T) {
tests := []isUtf8Test{
{"foo", true},
{"Straße", true},
{string([]uint8{65, 234, 234, 192, 23, 123}), false},
{string([]uint8{65, 97}), true},
}
for idx, test := range tests {
if isValidUtf8(test.s) != test.e {
t.Errorf("expected isutf8==%d for test index %d", test.e, idx)
}
}
}
const kExpectedHeader = `{"camliVersion"`
func TestJson(t *testing.T) {
m := NewMapForFileName("schema_test.go")
json, err := MapToCamliJson(m)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
t.Logf("Got json: [%s]\n", json)
// TODO: test it parses back
if !strings.HasPrefix(json, kExpectedHeader) {
t.Errorf("JSON does't start with expected header.")
}
}