github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_vendor/src/golang.org/x/tools/godoc/vfs/mapfs/mapfs.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package mapfs file provides an implementation of the FileSystem
     6  // interface based on the contents of a map[string]string.
     7  package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs"
     8  
     9  import (
    10  	"io"
    11  	"os"
    12  	pathpkg "path"
    13  	"sort"
    14  	"strings"
    15  	"time"
    16  
    17  	"golang.org/x/tools/godoc/vfs"
    18  )
    19  
    20  // New returns a new FileSystem from the provided map.
    21  // Map keys should be forward slash-separated pathnames
    22  // and not contain a leading slash.
    23  func New(m map[string]string) vfs.FileSystem {
    24  	return mapFS(m)
    25  }
    26  
    27  // mapFS is the map based implementation of FileSystem
    28  type mapFS map[string]string
    29  
    30  func (fs mapFS) String() string { return "mapfs" }
    31  
    32  func (fs mapFS) RootType(p string) vfs.RootType {
    33  	return ""
    34  }
    35  
    36  func (fs mapFS) Close() error { return nil }
    37  
    38  func filename(p string) string {
    39  	return strings.TrimPrefix(p, "/")
    40  }
    41  
    42  func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
    43  	b, ok := fs[filename(p)]
    44  	if !ok {
    45  		return nil, os.ErrNotExist
    46  	}
    47  	return nopCloser{strings.NewReader(b)}, nil
    48  }
    49  
    50  func fileInfo(name, contents string) os.FileInfo {
    51  	return mapFI{name: pathpkg.Base(name), size: len(contents)}
    52  }
    53  
    54  func dirInfo(name string) os.FileInfo {
    55  	return mapFI{name: pathpkg.Base(name), dir: true}
    56  }
    57  
    58  func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
    59  	b, ok := fs[filename(p)]
    60  	if ok {
    61  		return fileInfo(p, b), nil
    62  	}
    63  	ents, _ := fs.ReadDir(p)
    64  	if len(ents) > 0 {
    65  		return dirInfo(p), nil
    66  	}
    67  	return nil, os.ErrNotExist
    68  }
    69  
    70  func (fs mapFS) Stat(p string) (os.FileInfo, error) {
    71  	return fs.Lstat(p)
    72  }
    73  
    74  // slashdir returns path.Dir(p), but special-cases paths not beginning
    75  // with a slash to be in the root.
    76  func slashdir(p string) string {
    77  	d := pathpkg.Dir(p)
    78  	if d == "." {
    79  		return "/"
    80  	}
    81  	if strings.HasPrefix(p, "/") {
    82  		return d
    83  	}
    84  	return "/" + d
    85  }
    86  
    87  func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
    88  	p = pathpkg.Clean(p)
    89  	var ents []string
    90  	fim := make(map[string]os.FileInfo) // base -> fi
    91  	for fn, b := range fs {
    92  		dir := slashdir(fn)
    93  		isFile := true
    94  		var lastBase string
    95  		for {
    96  			if dir == p {
    97  				base := lastBase
    98  				if isFile {
    99  					base = pathpkg.Base(fn)
   100  				}
   101  				if fim[base] == nil {
   102  					var fi os.FileInfo
   103  					if isFile {
   104  						fi = fileInfo(fn, b)
   105  					} else {
   106  						fi = dirInfo(base)
   107  					}
   108  					ents = append(ents, base)
   109  					fim[base] = fi
   110  				}
   111  			}
   112  			if dir == "/" {
   113  				break
   114  			} else {
   115  				isFile = false
   116  				lastBase = pathpkg.Base(dir)
   117  				dir = pathpkg.Dir(dir)
   118  			}
   119  		}
   120  	}
   121  	if len(ents) == 0 {
   122  		return nil, os.ErrNotExist
   123  	}
   124  
   125  	sort.Strings(ents)
   126  	var list []os.FileInfo
   127  	for _, dir := range ents {
   128  		list = append(list, fim[dir])
   129  	}
   130  	return list, nil
   131  }
   132  
   133  // mapFI is the map-based implementation of FileInfo.
   134  type mapFI struct {
   135  	name string
   136  	size int
   137  	dir  bool
   138  }
   139  
   140  func (fi mapFI) IsDir() bool        { return fi.dir }
   141  func (fi mapFI) ModTime() time.Time { return time.Time{} }
   142  func (fi mapFI) Mode() os.FileMode {
   143  	if fi.IsDir() {
   144  		return 0755 | os.ModeDir
   145  	}
   146  	return 0444
   147  }
   148  func (fi mapFI) Name() string     { return pathpkg.Base(fi.name) }
   149  func (fi mapFI) Size() int64      { return int64(fi.size) }
   150  func (fi mapFI) Sys() interface{} { return nil }
   151  
   152  type nopCloser struct {
   153  	io.ReadSeeker
   154  }
   155  
   156  func (nc nopCloser) Close() error { return nil }