// precalcNextBuf follows the next link in line and loads it from the DAGService, // setting the next buffer to read from func (dr *DagReader) precalcNextBuf() error { if dr.position >= len(dr.node.Links) { return io.EOF } nxt, err := dr.node.Links[dr.position].GetNode(dr.serv) if err != nil { return err } pb := new(ftpb.Data) err = proto.Unmarshal(nxt.Data, pb) if err != nil { return err } dr.position++ switch pb.GetType() { case ftpb.Data_Directory: // A directory should not exist within a file return ft.ErrInvalidDirLocation case ftpb.Data_File: //TODO: this *should* work, needs testing first log.Warning("Running untested code for multilayered indirect FS reads.") subr, err := NewDagReader(nxt, dr.serv) if err != nil { return err } dr.buf = subr return nil case ftpb.Data_Raw: dr.buf = bytes.NewBuffer(pb.GetData()) return nil default: return ft.ErrUnrecognizedType } }
func UnwrapData(data []byte) ([]byte, error) { pbdata := new(pb.Data) err := proto.Unmarshal(data, pbdata) if err != nil { return nil, err } return pbdata.GetData(), nil }
func (mb *MultiBlock) GetBytes() ([]byte, error) { pbn := new(pb.Data) t := pb.Data_File pbn.Type = &t pbn.Filesize = proto.Uint64(uint64(len(mb.Data)) + mb.subtotal) pbn.Blocksizes = mb.blocksizes pbn.Data = mb.Data return proto.Marshal(pbn) }
// Returns Bytes that represent a Directory func FolderPBData() []byte { pbfile := new(pb.Data) typ := pb.Data_Directory pbfile.Type = &typ data, err := proto.Marshal(pbfile) if err != nil { //this really shouldnt happen, i promise panic(err) } return data }
func WrapData(b []byte) []byte { pbdata := new(pb.Data) typ := pb.Data_Raw pbdata.Data = b pbdata.Type = &typ out, err := proto.Marshal(pbdata) if err != nil { // This shouldnt happen. seriously. panic(err) } return out }
func FilePBData(data []byte, totalsize uint64) []byte { pbfile := new(pb.Data) typ := pb.Data_File pbfile.Type = &typ pbfile.Data = data pbfile.Filesize = proto.Uint64(totalsize) data, err := proto.Marshal(pbfile) if err != nil { // This really shouldnt happen, i promise // The only failure case for marshal is if required fields // are not filled out, and they all are. If the proto object // gets changed and nobody updates this function, the code // should panic due to programmer error panic(err) } return data }
func DataSize(data []byte) (uint64, error) { pbdata := new(pb.Data) err := proto.Unmarshal(data, pbdata) if err != nil { return 0, err } switch pbdata.GetType() { case pb.Data_Directory: return 0, errors.New("Cant get data size of directory!") case pb.Data_File: return pbdata.GetFilesize(), nil case pb.Data_Raw: return uint64(len(pbdata.GetData())), nil default: return 0, errors.New("Unrecognized node data type!") } }
// NewDagReader creates a new reader object that reads the data represented by the given // node, using the passed in DAGService for data retreival func NewDagReader(n *mdag.Node, serv mdag.DAGService) (io.Reader, error) { pb := new(ftpb.Data) err := proto.Unmarshal(n.Data, pb) if err != nil { return nil, err } switch pb.GetType() { case ftpb.Data_Directory: // Dont allow reading directories return nil, ErrIsDir case ftpb.Data_File: return &DagReader{ node: n, serv: serv, buf: bytes.NewBuffer(pb.GetData()), }, nil case ftpb.Data_Raw: // Raw block will just be a single level, return a byte buffer return bytes.NewBuffer(pb.GetData()), nil default: return nil, ft.ErrUnrecognizedType } }