github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/unixfs/format.go (about) 1 // Package format implements a data format for files in the ipfs filesystem 2 // It is not the only format in ipfs, but it is the one that the filesystem assumes 3 package unixfs 4 5 import ( 6 "errors" 7 8 proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" 9 pb "github.com/jbenet/go-ipfs/unixfs/pb" 10 ) 11 12 var ErrMalformedFileFormat = errors.New("malformed data in file format") 13 var ErrInvalidDirLocation = errors.New("found directory node in unexpected place") 14 var ErrUnrecognizedType = errors.New("unrecognized node type") 15 16 func FromBytes(data []byte) (*pb.Data, error) { 17 pbdata := new(pb.Data) 18 err := proto.Unmarshal(data, pbdata) 19 if err != nil { 20 return nil, err 21 } 22 return pbdata, nil 23 } 24 25 func FilePBData(data []byte, totalsize uint64) []byte { 26 pbfile := new(pb.Data) 27 typ := pb.Data_File 28 pbfile.Type = &typ 29 pbfile.Data = data 30 pbfile.Filesize = proto.Uint64(totalsize) 31 32 data, err := proto.Marshal(pbfile) 33 if err != nil { 34 // This really shouldnt happen, i promise 35 // The only failure case for marshal is if required fields 36 // are not filled out, and they all are. If the proto object 37 // gets changed and nobody updates this function, the code 38 // should panic due to programmer error 39 panic(err) 40 } 41 return data 42 } 43 44 // Returns Bytes that represent a Directory 45 func FolderPBData() []byte { 46 pbfile := new(pb.Data) 47 typ := pb.Data_Directory 48 pbfile.Type = &typ 49 50 data, err := proto.Marshal(pbfile) 51 if err != nil { 52 //this really shouldnt happen, i promise 53 panic(err) 54 } 55 return data 56 } 57 58 func WrapData(b []byte) []byte { 59 pbdata := new(pb.Data) 60 typ := pb.Data_Raw 61 pbdata.Data = b 62 pbdata.Type = &typ 63 64 out, err := proto.Marshal(pbdata) 65 if err != nil { 66 // This shouldnt happen. seriously. 67 panic(err) 68 } 69 70 return out 71 } 72 73 func UnwrapData(data []byte) ([]byte, error) { 74 pbdata := new(pb.Data) 75 err := proto.Unmarshal(data, pbdata) 76 if err != nil { 77 return nil, err 78 } 79 return pbdata.GetData(), nil 80 } 81 82 func DataSize(data []byte) (uint64, error) { 83 pbdata := new(pb.Data) 84 err := proto.Unmarshal(data, pbdata) 85 if err != nil { 86 return 0, err 87 } 88 89 switch pbdata.GetType() { 90 case pb.Data_Directory: 91 return 0, errors.New("Cant get data size of directory!") 92 case pb.Data_File: 93 return pbdata.GetFilesize(), nil 94 case pb.Data_Raw: 95 return uint64(len(pbdata.GetData())), nil 96 default: 97 return 0, errors.New("Unrecognized node data type!") 98 } 99 } 100 101 type MultiBlock struct { 102 Data []byte 103 blocksizes []uint64 104 subtotal uint64 105 } 106 107 func (mb *MultiBlock) AddBlockSize(s uint64) { 108 mb.subtotal += s 109 mb.blocksizes = append(mb.blocksizes, s) 110 } 111 112 func (mb *MultiBlock) GetBytes() ([]byte, error) { 113 pbn := new(pb.Data) 114 t := pb.Data_File 115 pbn.Type = &t 116 pbn.Filesize = proto.Uint64(uint64(len(mb.Data)) + mb.subtotal) 117 pbn.Blocksizes = mb.blocksizes 118 pbn.Data = mb.Data 119 return proto.Marshal(pbn) 120 }