git » chasquid » commit 960c348

protoio: I/O helpers for protobuf messages

author Alberto Bertogli
2016-09-17 22:04:20 UTC
committer Alberto Bertogli
2016-10-09 23:51:03 UTC
parent e2fdcb370561d4a21a9781bf667fbe6034b80d40

protoio: I/O helpers for protobuf messages

internal/protoio/protoio.go +48 -0
internal/protoio/protoio_test.go +67 -0
internal/protoio/testpb/dummy.go +3 -0
internal/protoio/testpb/testpb.pb.go +53 -0
internal/protoio/testpb/testpb.proto +8 -0

diff --git a/internal/protoio/protoio.go b/internal/protoio/protoio.go
new file mode 100644
index 0000000..d17a98a
--- /dev/null
+++ b/internal/protoio/protoio.go
@@ -0,0 +1,48 @@
+// Package protoio contains I/O functions for protocol buffers.
+package protoio
+
+import (
+	"io/ioutil"
+	"os"
+
+	"blitiri.com.ar/go/chasquid/internal/safeio"
+
+	"github.com/golang/protobuf/proto"
+)
+
+// ReadMessage reads a protocol buffer message from fname, and unmarshalls it
+// into pb.
+func ReadMessage(fname string, pb proto.Message) error {
+	in, err := ioutil.ReadFile(fname)
+	if err != nil {
+		return err
+	}
+	return proto.Unmarshal(in, pb)
+}
+
+// ReadTextMessage reads a text format protocol buffer message from fname, and
+// unmarshalls it into pb.
+func ReadTextMessage(fname string, pb proto.Message) error {
+	in, err := ioutil.ReadFile(fname)
+	if err != nil {
+		return err
+	}
+	return proto.UnmarshalText(string(in), pb)
+}
+
+// WriteMessage marshals pb and atomically writes it into fname.
+func WriteMessage(fname string, pb proto.Message, perm os.FileMode) error {
+	out, err := proto.Marshal(pb)
+	if err != nil {
+		return err
+	}
+
+	return safeio.WriteFile(fname, out, perm)
+}
+
+// WriteTextMessage marshals pb in text format and atomically writes it into
+// fname.
+func WriteTextMessage(fname string, pb proto.Message, perm os.FileMode) error {
+	out := proto.MarshalTextString(pb)
+	return safeio.WriteFile(fname, []byte(out), perm)
+}
diff --git a/internal/protoio/protoio_test.go b/internal/protoio/protoio_test.go
new file mode 100644
index 0000000..7260a00
--- /dev/null
+++ b/internal/protoio/protoio_test.go
@@ -0,0 +1,67 @@
+package protoio
+
+import (
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"blitiri.com.ar/go/chasquid/internal/protoio/testpb"
+)
+
+func mustTempDir(t *testing.T) string {
+	dir, err := ioutil.TempDir("", "safeio_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = os.Chdir(dir)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Logf("test directory: %q", dir)
+
+	return dir
+}
+
+func TestBin(t *testing.T) {
+	dir := mustTempDir(t)
+	pb := &testpb.M{"hola"}
+
+	if err := WriteMessage("f", pb, 0600); err != nil {
+		t.Error(err)
+	}
+
+	pb2 := &testpb.M{}
+	if err := ReadMessage("f", pb2); err != nil {
+		t.Error(err)
+	}
+	if pb.Content != pb2.Content {
+		t.Errorf("content mismatch, got %q, expected %q", pb2.Content, pb.Content)
+	}
+
+	if !t.Failed() {
+		os.RemoveAll(dir)
+	}
+}
+
+func TestText(t *testing.T) {
+	dir := mustTempDir(t)
+	pb := &testpb.M{"hola"}
+
+	if err := WriteTextMessage("f", pb, 0600); err != nil {
+		t.Error(err)
+	}
+
+	pb2 := &testpb.M{}
+	if err := ReadTextMessage("f", pb2); err != nil {
+		t.Error(err)
+	}
+	if pb.Content != pb2.Content {
+		t.Errorf("content mismatch, got %q, expected %q", pb2.Content, pb.Content)
+	}
+
+	if !t.Failed() {
+		os.RemoveAll(dir)
+	}
+}
diff --git a/internal/protoio/testpb/dummy.go b/internal/protoio/testpb/dummy.go
new file mode 100644
index 0000000..f9c04d1
--- /dev/null
+++ b/internal/protoio/testpb/dummy.go
@@ -0,0 +1,3 @@
+package testpb
+
+//go:generate protoc --go_out=. testpb.proto
diff --git a/internal/protoio/testpb/testpb.pb.go b/internal/protoio/testpb/testpb.pb.go
new file mode 100644
index 0000000..f20e2c4
--- /dev/null
+++ b/internal/protoio/testpb/testpb.pb.go
@@ -0,0 +1,53 @@
+// Code generated by protoc-gen-go.
+// source: testpb.proto
+// DO NOT EDIT!
+
+/*
+Package testpb is a generated protocol buffer package.
+
+It is generated from these files:
+	testpb.proto
+
+It has these top-level messages:
+	M
+*/
+package testpb
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type M struct {
+	Content string `protobuf:"bytes,1,opt,name=content" json:"content,omitempty"`
+}
+
+func (m *M) Reset()                    { *m = M{} }
+func (m *M) String() string            { return proto.CompactTextString(m) }
+func (*M) ProtoMessage()               {}
+func (*M) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func init() {
+	proto.RegisterType((*M)(nil), "testpb.M")
+}
+
+func init() { proto.RegisterFile("testpb.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+	// 69 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x49, 0x2d, 0x2e,
+	0x29, 0x48, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0x44, 0xb8, 0x18,
+	0x7d, 0x85, 0xf8, 0xb9, 0xd8, 0x93, 0xf3, 0xf3, 0x4a, 0x52, 0xf3, 0x4a, 0x24, 0x18, 0x15, 0x18,
+	0x35, 0x38, 0x93, 0xd8, 0xc0, 0x8a, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x18, 0x08,
+	0x20, 0x34, 0x00, 0x00, 0x00,
+}
diff --git a/internal/protoio/testpb/testpb.proto b/internal/protoio/testpb/testpb.proto
new file mode 100644
index 0000000..a93ffcb
--- /dev/null
+++ b/internal/protoio/testpb/testpb.proto
@@ -0,0 +1,8 @@
+
+syntax = "proto3";
+
+package testpb;
+
+message M {
+	string content = 1;
+}