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  }