// 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 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 } }