github.com/puellanivis/breton@v0.2.16/lib/files/wrapper/info.go (about)

     1  // Package wrapper provides a files.Files implementation based on a bytes.Buffer backing store, and WriteFn callbacks.
     2  package wrapper
     3  
     4  import (
     5  	"net/url"
     6  	"os"
     7  	"sync"
     8  	"syscall"
     9  	"time"
    10  )
    11  
    12  // Info provides an implementation of os.FileInfo with arbitrary information suitable for a url.
    13  type Info struct {
    14  	mu sync.RWMutex
    15  
    16  	name string
    17  	uri  *url.URL
    18  	sz   int64
    19  	mode os.FileMode
    20  	t    time.Time
    21  }
    22  
    23  // NewInfo returns a new Info set with the url, size and time specified.
    24  func NewInfo(uri *url.URL, size int, t time.Time) *Info {
    25  	return &Info{
    26  		uri:  uri,
    27  		sz:   int64(size),
    28  		mode: os.FileMode(0644),
    29  		t:    t,
    30  	}
    31  }
    32  
    33  // SetName sets a new string as the filename.
    34  func (fi *Info) SetName(name string) {
    35  	if fi == nil {
    36  		return
    37  	}
    38  
    39  	fi.mu.Lock()
    40  	defer fi.mu.Unlock()
    41  
    42  	fi.name = name
    43  	fi.uri = nil
    44  }
    45  
    46  // SetNameFromURL sets a new URL as the filename.
    47  func (fi *Info) SetNameFromURL(uri *url.URL) {
    48  	if fi == nil {
    49  		return
    50  	}
    51  
    52  	fi.mu.Lock()
    53  	defer fi.mu.Unlock()
    54  
    55  	fi.uri = uri
    56  	fi.name = ""
    57  }
    58  
    59  func (fi *Info) fixName() string {
    60  	if fi.name != "" || fi.uri == nil {
    61  		// Nothing to fix.
    62  		// Likely, someone else already fixed the name while we were waiting on the mutex.
    63  		return fi.name
    64  	}
    65  
    66  	fi.name = fi.uri.String()
    67  
    68  	if fi.name == "" {
    69  		// If we got an empty string from the url, then we need to remove the url,
    70  		// otherwise we will forever keep trying to fix the name.
    71  		fi.uri = nil
    72  	}
    73  
    74  	return fi.name
    75  }
    76  
    77  // Name returns the filename of the Info, if name == "" and there is a url,
    78  // then it renders the url, and returns that as the name.
    79  func (fi *Info) Name() string {
    80  	if fi == nil {
    81  		return ""
    82  	}
    83  
    84  	fi.mu.RLock()
    85  	name, uri := fi.name, fi.uri
    86  	fi.mu.RUnlock()
    87  
    88  	if name == "" && uri != nil {
    89  		fi.mu.Lock()
    90  		defer fi.mu.Unlock()
    91  
    92  		return fi.fixName()
    93  	}
    94  
    95  	return name
    96  }
    97  
    98  // Size returns the size declared in the Info.
    99  func (fi *Info) Size() int64 {
   100  	if fi == nil {
   101  		return 0
   102  	}
   103  
   104  	fi.mu.RLock()
   105  	defer fi.mu.RUnlock()
   106  
   107  	return fi.sz
   108  }
   109  
   110  // SetSize sets a new size in the Info.
   111  func (fi *Info) SetSize(size int) {
   112  	if fi == nil {
   113  		return
   114  	}
   115  
   116  	fi.mu.Lock()
   117  	defer fi.mu.Unlock()
   118  
   119  	fi.sz = int64(size)
   120  }
   121  
   122  // Mode returns the last value set via Chmod(), this defaults to os.FileMode(0644)
   123  func (fi *Info) Mode() (mode os.FileMode) {
   124  	if fi == nil {
   125  		return mode
   126  	}
   127  
   128  	fi.mu.RLock()
   129  	defer fi.mu.RUnlock()
   130  
   131  	return fi.mode
   132  }
   133  
   134  // Chmod sets the os.FileMode to be returned from Mode().
   135  func (fi *Info) Chmod(mode os.FileMode) error {
   136  	if fi == nil {
   137  		return syscall.EINVAL
   138  	}
   139  
   140  	fi.mu.Lock()
   141  	defer fi.mu.Unlock()
   142  
   143  	fi.mode = mode
   144  	return nil
   145  }
   146  
   147  // ModTime returns the modification time declared in the Info.
   148  func (fi *Info) ModTime() (t time.Time) {
   149  	if fi == nil {
   150  		return t
   151  	}
   152  
   153  	fi.mu.RLock()
   154  	defer fi.mu.RUnlock()
   155  
   156  	return fi.t
   157  }
   158  
   159  // SetModTime sets the modification time in the Info to the time.Time given.
   160  func (fi *Info) SetModTime(t time.Time) {
   161  	fi.mu.Lock()
   162  	defer fi.mu.Unlock()
   163  
   164  	fi.t = t
   165  }
   166  
   167  // IsDir returns true if a prior Chmod set os.ModeDir.
   168  func (fi *Info) IsDir() bool {
   169  	if fi == nil {
   170  		return false
   171  	}
   172  
   173  	fi.mu.RLock()
   174  	defer fi.mu.RUnlock()
   175  
   176  	return fi.mode&os.ModeDir != 0
   177  }
   178  
   179  // Sys returns the Info object itself, as it is already the underlying data source.
   180  func (fi *Info) Sys() interface{} {
   181  	if fi == nil {
   182  		// return an untyped nil here.
   183  		return nil
   184  	}
   185  
   186  	return fi
   187  }
   188  
   189  // Stat returns the Info object itself, this allows for a simple embedding of the Info into a struct.
   190  func (fi *Info) Stat() (os.FileInfo, error) {
   191  	// if fi is nil, we intentionally return a typed nil here.
   192  	return fi, nil
   193  }