Skip to content

Commit

Permalink
files2.0: Add some convenience functions
Browse files Browse the repository at this point in the history
  • Loading branch information
magik6k committed Dec 3, 2018
1 parent 2936a34 commit f732b39
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 80 deletions.
8 changes: 0 additions & 8 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ type DirEntry interface {

// Node returns the file referenced by this DirEntry
Node() Node

// File is an alias for ent.Node().(File). If the file isn't a regular
// file, nil value will be returned
File() File

// Dir is an alias for ent.Node().(directory). If the file isn't a directory,
// nil value will be returned
Dir() Directory
}

// DirIterator is a iterator over directory entries.
Expand Down
16 changes: 7 additions & 9 deletions file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,25 @@ package files

import (
"io"
"io/ioutil"
"mime/multipart"
"strings"
"testing"
)

func TestSliceFiles(t *testing.T) {
files := []DirEntry{
FileEntry("", NewReaderFile(ioutil.NopCloser(strings.NewReader("Some text!\n")), nil)),
FileEntry("", NewReaderFile(ioutil.NopCloser(strings.NewReader("beep")), nil)),
FileEntry("", NewReaderFile(ioutil.NopCloser(strings.NewReader("boop")), nil)),
}
sf := DirFrom(map[string]Node{
"1": FileFrom([]byte("Some text!\n")),
"2": FileFrom([]byte("beep")),
"3": FileFrom([]byte("boop")),
})
buf := make([]byte, 20)

sf := NewSliceFile(files)
it := sf.Entries()

if !it.Next() {
t.Fatal("Expected a file")
}
rf := it.File()
rf := ToFile(it.Node())
if rf == nil {
t.Fatal("Expected a regular file")
}
Expand All @@ -48,7 +46,7 @@ func TestSliceFiles(t *testing.T) {

func TestReaderFiles(t *testing.T) {
message := "beep boop"
rf := NewReaderFile(ioutil.NopCloser(strings.NewReader(message)), nil)
rf := FileFrom([]byte(message))
buf := make([]byte, len(message))

if n, err := rf.Read(buf); n == 0 || err != nil {
Expand Down
5 changes: 5 additions & 0 deletions linkfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ func (lf *Symlink) Size() (int64, error) {
return 0, ErrNotSupported
}

func ToSymlink(n Node) *Symlink {
l, _ := n.(*Symlink)
return l
}

var _ File = &Symlink{}
39 changes: 18 additions & 21 deletions multifilereader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@ package files

import (
"io"
"io/ioutil"
"mime/multipart"
"strings"
"testing"
)

var text = "Some text! :)"

func getTestMultiFileReader(t *testing.T) *MultiFileReader {
fileset := []DirEntry{
FileEntry("file.txt", NewReaderFile(ioutil.NopCloser(strings.NewReader(text)), nil)),
FileEntry("boop", NewSliceFile([]DirEntry{
FileEntry("a.txt", NewReaderFile(ioutil.NopCloser(strings.NewReader("bleep")), nil)),
FileEntry("b.txt", NewReaderFile(ioutil.NopCloser(strings.NewReader("bloop")), nil)),
})),
FileEntry("beep.txt", NewReaderFile(ioutil.NopCloser(strings.NewReader("beep")), nil)),
}
sf := NewSliceFile(fileset)
sf := DirFrom(map[string]Node{
"file.txt": FileFrom([]byte(text)),
"boop": DirFrom(map[string]Node{
"a.txt": FileFrom([]byte("bleep")),
"b.txt": FileFrom([]byte("bloop")),
}),
"beep.txt": FileFrom([]byte("beep")),
})

// testing output by reading it with the go stdlib "mime/multipart" Reader
r, err := NewMultiFileReader(sf, true)
Expand All @@ -43,21 +40,21 @@ func TestMultiFileReaderToMultiFile(t *testing.T) {
}
it := md.Entries()

if !it.Next() || it.Name() != "file.txt" {
if !it.Next() || it.Name() != "beep.txt" {
t.Fatal("iterator didn't work as expected")
}

if !it.Next() || it.Name() != "boop" || it.Dir() == nil {
if !it.Next() || it.Name() != "boop" || DirFrom(it) == nil {
t.Fatal("iterator didn't work as expected")
}

subIt := it.Dir().Entries()
subIt := DirFrom(it).Entries()

if !subIt.Next() || subIt.Name() != "a.txt" || subIt.Dir() != nil {
if !subIt.Next() || subIt.Name() != "a.txt" || DirFrom(subIt) != nil {
t.Fatal("iterator didn't work as expected")
}

if !subIt.Next() || subIt.Name() != "b.txt" || subIt.Dir() != nil {
if !subIt.Next() || subIt.Name() != "b.txt" || DirFrom(subIt) != nil {
t.Fatal("iterator didn't work as expected")
}

Expand All @@ -70,7 +67,7 @@ func TestMultiFileReaderToMultiFile(t *testing.T) {
t.Fatal("iterator didn't work as expected")
}

if !it.Next() || it.Name() != "beep.txt" || it.Dir() != nil || it.Err() != nil {
if !it.Next() || it.Name() != "file.txt" || DirFrom(it) != nil || it.Err() != nil {
t.Fatal("iterator didn't work as expected")
}

Expand All @@ -96,13 +93,13 @@ func TestOutput(t *testing.T) {
if !ok {
t.Fatal("Expected file to be a regular file")
}
if mpname != "file.txt" {
if mpname != "beep.txt" {
t.Fatal("Expected filename to be \"file.txt\"")
}
if n, err := mpr.Read(buf); n != len(text) || err != nil {
if n, err := mpr.Read(buf); n != 4 || err != nil {
t.Fatal("Expected to read from file", n, err)
}
if string(buf[:len(text)]) != text {
if string(buf[:4]) != "beep" {
t.Fatal("Data read was different than expected")
}

Expand Down Expand Up @@ -165,7 +162,7 @@ func TestOutput(t *testing.T) {
if mpf == nil || err != nil {
t.Fatal("Expected non-nil MultipartFile, nil error")
}
if mpname != "beep.txt" {
if mpname != "file.txt" {
t.Fatal("Expected filename to be \"b.txt\"")
}

Expand Down
8 changes: 0 additions & 8 deletions multipartfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,6 @@ func (it *multipartIterator) Node() Node {
return it.curFile
}

func (it *multipartIterator) File() File {
return castRegular(it.Node())
}

func (it *multipartIterator) Dir() Directory {
return castDir(it.Node())
}

func (it *multipartIterator) Next() bool {
if it.f.Reader == nil {
return false
Expand Down
18 changes: 0 additions & 18 deletions serialfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ func (it *serialIterator) Node() Node {
return it.curFile
}

func (it *serialIterator) File() File {
return castRegular(it.Node())
}

func (it *serialIterator) Dir() Directory {
return castDir(it.Node())
}

func (it *serialIterator) Next() bool {
// if there aren't any files left in the root directory, we're done
if len(it.files) == 0 {
Expand Down Expand Up @@ -182,15 +174,5 @@ func (f *serialFile) Size() (int64, error) {
return du, err
}

func castRegular(f Node) File {
r, _ := f.(File)
return r
}

func castDir(f Node) Directory {
d, _ := f.(Directory)
return d
}

var _ Directory = &serialFile{}
var _ DirIterator = &serialIterator{}
16 changes: 0 additions & 16 deletions slicefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ func (e fileEntry) Node() Node {
return e.file
}

func (e fileEntry) File() File {
return castRegular(e.file)
}

func (e fileEntry) Dir() Directory {
return castDir(e.file)
}

func FileEntry(name string, file Node) DirEntry {
return fileEntry{
name: name,
Expand All @@ -41,14 +33,6 @@ func (it *sliceIterator) Node() Node {
return it.files[it.n].Node()
}

func (it *sliceIterator) File() File {
return it.files[it.n].File()
}

func (it *sliceIterator) Dir() Directory {
return it.files[it.n].Dir()
}

func (it *sliceIterator) Next() bool {
it.n++
return it.n < len(it.files)
Expand Down
80 changes: 80 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package files

import (
"bytes"
"io"
"io/ioutil"
"sort"
)

// ToFile is an alias for n.(File). If the file isn't a regular file, nil value
// will be returned
func ToFile(n Node) File {
f, _ := n.(File)
return f
}

// ToDir is an alias for n.(Directory). If the file isn't directory, a nil value
// will be returned
func ToDir(n Node) Directory {
d, _ := n.(Directory)
return d
}

// FileFrom is a convenience function which tries to extract or create new file
// from provided value. If a passed value can't be turned into a File, nil will
// be returned.
//
// Supported types:
// * files.File (cast from Node)
// * DirEntry / DirIterator (cast from e.Node())
// * []byte (wrapped into NewReaderFile)
// * io.Reader / io.ReadCloser (wrapped into NewReaderFile)
func FileFrom(n interface{}) File {
switch f := n.(type) {
case File:
return f
case DirEntry:
return ToFile(f.Node())
case []byte:
return NewReaderFile(ioutil.NopCloser(bytes.NewReader(f)), nil)
case io.ReadCloser:
return NewReaderFile(f, nil)
case io.Reader:
return NewReaderFile(ioutil.NopCloser(f), nil)
default:
return nil
}
}

// DirFrom is a convenience function which tries to extract or create new
// directory from the provided value. If a passed value can't be turned into a
// Directory, nil will be returned.
//
// Supported types:
// * files.File (cast from Node)
// * DirEntry (cast from e.Node())
// * DirIterator (current file, cast from e.Node())
// * []DirEntry (wrapped into NewSliceFile)
// * map[string]Node (wrapped into NewSliceFile)
func DirFrom(n interface{}) Directory {
switch f := n.(type) {
case Directory:
return f
case DirEntry:
return ToDir(f.Node())
case []DirEntry:
return NewSliceFile(f)
case map[string]Node:
ents := make([]DirEntry, 0, len(f))
for name, nd := range f {
ents = append(ents, FileEntry(name, nd))
}
sort.Slice(ents, func(i, j int) bool {
return ents[i].Name() < ents[j].Name()
})
return NewSliceFile(ents)
default:
return nil
}
}

0 comments on commit f732b39

Please sign in to comment.