func (node *Node) resetAllModTime(t time.Time) {
	node.modTime = t
	for _, c := range node.Childs {
		c.resetAllModTime(t)
	}
}
resetAllModTime set the modTime of node and its child to the t.
This method is only intended for testing.
package memfs
import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"time"
	"github.com/shuLhan/share/lib/ascii"
	libbytes "github.com/shuLhan/share/lib/bytes"
)
var (
	errOffset = errors.New("Seek: invalid offset")
	errWhence = errors.New("Seek: invalid whence")
)
type Node struct {
	os.FileInfo
	http.File
	SysPath         string   
	Path            string   
	Content         []byte   
	ContentType     string   
	ContentEncoding string   
	Parent          *Node    
	Childs          []*Node  
	GenFuncName     string   
	name    string       
	modTime time.Time    
	mode    os.FileMode  
	size    int64        
	plainv  []byte       
	lowerv  []byte       
	off     int64        
}
func NewNode(parent *Node, fi os.FileInfo, maxFileSize int64) (node *Node, err error) {
	if fi == nil {
		return nil, nil
	}
	var (
		logp    = "NewNode"
		sysPath string
		relPath string
	)
	sysPath = filepath.Join(parent.SysPath, fi.Name())
	relPath = path.Join(parent.Path, fi.Name())
	node = &Node{
		SysPath: sysPath,
		Path:    relPath,
		name:    fi.Name(),
		modTime: fi.ModTime(),
		mode:    fi.Mode(),
		size:    fi.Size(),
		Parent:  parent,
	}
	node.generateFuncName(sysPath)
	if node.mode.IsDir() {
		node.size = 0
		return node, nil
	}
	if fi.Mode()&os.ModeSymlink != 0 {
		sysPath, err = filepath.EvalSymlinks(sysPath)
		if err != nil {
			return nil, fmt.Errorf("%s: %w", logp, err)
		}
		fi, err = os.Lstat(sysPath)
		if err != nil {
			return nil, fmt.Errorf("%s: %w", logp, err)
		}
		node.mode = fi.Mode()
		if node.mode.IsDir() {
			node.size = 0
			return node, nil
		}
		node.size = fi.Size()
	}
	err = node.updateContent(maxFileSize)
	if err != nil {
		return nil, fmt.Errorf("%s: %w", logp, err)
	}
	err = node.updateContentType()
	if err != nil {
		return nil, fmt.Errorf("%s: %w", logp, err)
	}
	return node, nil
}
func (node *Node) AddChild(child *Node) {
	if child.modTime.IsZero() {
		child.modTime = time.Now()
	}
	node.Childs = append(node.Childs, child)
	child.Parent = node
}
func (node *Node) Close() error {
	node.off = 0
	return nil
}
func (node *Node) Decode() ([]byte, error) {
	if len(node.ContentEncoding) == 0 {
		node.plainv = node.Content
		return node.plainv, nil
	}
	logp := "Decode"
	node.plainv = node.plainv[:0]
	if node.ContentEncoding == EncodingGzip {
		r, err := gzip.NewReader(bytes.NewReader(node.Content))
		if err != nil {
			return nil, fmt.Errorf("%s: %w", logp, err)
		}
		buf := make([]byte, 1024)
		for {
			n, err := r.Read(buf)
			if n > 0 {
				node.plainv = append(node.plainv, buf[:n]...)
			}
			if err != nil {
				if err == io.EOF {
					break
				}
				return nil, fmt.Errorf("%s: %w", logp, err)
			}
			buf = buf[0:]
		}
	}
	return node.plainv, nil
}
func (node *Node) Encode(content []byte) (err error) {
	logp := "Encode"
	node.plainv = content
	node.lowerv = bytes.ToLower(content)
	switch node.ContentEncoding {
	case EncodingGzip:
		var buf bytes.Buffer
		gz := gzip.NewWriter(&buf)
		_, err = gz.Write(content)
		if err != nil {
			_ = gz.Close()
			return fmt.Errorf("%s: %w", logp, err)
		}
		err = gz.Close()
		if err != nil {
			return fmt.Errorf("%s: %w", logp, err)
		}
		node.Content = libbytes.Copy(buf.Bytes())
	default:
		node.Content = content
	}
	return nil
}
func (node *Node) IsDir() bool {
	return node.mode.IsDir()
}
func (node *Node) MarshalJSON() ([]byte, error) {
	var buf bytes.Buffer
	node.packAsJson(&buf, 0)
	return buf.Bytes(), nil
}
func (node *Node) ModTime() time.Time {
	return node.modTime
}
func (node *Node) Mode() os.FileMode {
	return node.mode
}
func (node *Node) Name() string {
	return node.name
}
func (node *Node) Read(p []byte) (n int, err error) {
	if len(p) == 0 {
		return 0, nil
	}
	if node.off >= node.size {
		return 0, fmt.Errorf("Read: %w", io.EOF)
	}
	n = copy(p, node.Content[node.off:])
	node.off += int64(n)
	return n, nil
}
func (node *Node) Readdir(count int) (fis []os.FileInfo, err error) {
	if !node.IsDir() {
		return nil, nil
	}
	if count <= 0 || count >= len(node.Childs) {
		fis = make([]os.FileInfo, len(node.Childs))
		for x := 0; x < len(node.Childs); x++ {
			fis[x] = node.Childs[x]
		}
		node.off = 0
		return fis, nil
	}
	if node.off >= int64(len(node.Childs)) {
		return nil, nil
	}
	count += int(node.off)
	if count >= len(node.Childs) {
		count = len(node.Childs)
	}
	fis = make([]os.FileInfo, 0, count-int(node.off))
	for _, child := range node.Childs[node.off:count] {
		fis = append(fis, child)
	}
	node.off = int64(count)
	return fis, nil
}
func (node *Node) Save(content []byte) (err error) {
	var (
		logp = "Save"
		f    *os.File
	)
	f, err = os.OpenFile(node.SysPath, os.O_WRONLY|os.O_TRUNC, node.mode.Perm())
	if err != nil {
		return fmt.Errorf("%s: %w", logp, err)
	}
	_, err = f.Write(content)
	if err != nil {
		return fmt.Errorf("%s: %w", logp, err)
	}
	err = f.Close()
	if err != nil {
		return fmt.Errorf("%s: %w", logp, err)
	}
	err = node.Encode(content)
	if err != nil {
		return fmt.Errorf("%s: %w", logp, err)
	}
	node.modTime = time.Now()
	node.size = int64(len(content))
	return nil
}
func (node *Node) Seek(offset int64, whence int) (int64, error) {
	switch whence {
	case io.SeekStart:
	case io.SeekCurrent:
		offset += node.off
	case io.SeekEnd:
		offset += node.size
	default:
		return 0, errWhence
	}
	if offset < 0 {
		return 0, errOffset
	}
	node.off = offset
	return node.off, nil
}
func (node *Node) SetModTime(modTime time.Time) {
	node.modTime = modTime
}
func (node *Node) SetModTimeUnix(seconds, nanoSeconds int64) {
	node.modTime = time.Unix(seconds, nanoSeconds)
}
func (node *Node) SetMode(mode os.FileMode) {
	node.mode = mode
}
func (node *Node) SetName(name string) {
	node.name = name
}
func (node *Node) SetSize(size int64) {
	node.size = size
}
func (node *Node) Size() int64 {
	return node.size
}
func (node *Node) Stat() (os.FileInfo, error) {
	return node, nil
}
func (node *Node) Sys() interface{} {
	return node
}
func (node *Node) addChild(
	sysPath string, fi os.FileInfo, maxFileSize int64,
) (child *Node, err error) {
	child, err = NewNode(node, fi, maxFileSize)
	if err != nil {
		return nil, fmt.Errorf("addChild: %w", err)
	}
	child.SysPath = sysPath
	node.Childs = append(node.Childs, child)
	return child, nil
}
func (node *Node) generateFuncName(in string) {
	syspath := string(libbytes.InReplace([]byte(in), []byte(ascii.LettersNumber), '_'))
	node.GenFuncName = "generate_" + syspath
}
func (node *Node) packAsJson(buf *bytes.Buffer, depth int) {
	isDir := node.IsDir()
	_ = buf.WriteByte('{')
	_, _ = fmt.Fprintf(buf, `"path":%q,`, node.Path)
	_, _ = fmt.Fprintf(buf, `"name":%q,`, node.name)
	_, _ = fmt.Fprintf(buf, `"content_type":%q,`, node.ContentType)
	_, _ = fmt.Fprintf(buf, `"mod_time":%d,`, node.modTime.Unix())
	_, _ = fmt.Fprintf(buf, `"mode_string":%q,`, node.mode)
	_, _ = fmt.Fprintf(buf, `"size":%d,`, node.size)
	_, _ = fmt.Fprintf(buf, `"is_dir":%t,`, isDir)
	if !isDir && depth == 0 {
		content := base64.StdEncoding.EncodeToString(node.Content)
		_, _ = fmt.Fprintf(buf, `"content":%q,`, content)
	}
	_, _ = fmt.Fprintf(buf, `"childs":`)
	if depth == 0 {
		_ = buf.WriteByte('[')
		for x, child := range node.Childs {
			if x > 0 {
				_ = buf.WriteByte(',')
			}
			child.packAsJson(buf, depth+1)
		}
		_ = buf.WriteByte(']')
	} else {
		_, _ = buf.WriteString("null")
	}
	_ = buf.WriteByte('}')
}
func (node *Node) removeChild(child *Node) *Node {
	for x := 0; x < len(node.Childs); x++ {
		if node.Childs[x] != child {
			continue
		}
		copy(node.Childs[x:], node.Childs[x+1:])
		n := len(node.Childs)
		node.Childs[n-1] = nil
		node.Childs = node.Childs[:n-1]
		child.Parent = nil
		child.Childs = nil
		return child
	}
	return nil
}