go-strfs/content.go

158 lines
3.3 KiB
Go
Raw Normal View History

2022-12-14 11:03:30 +00:00
package strfs
import (
"io"
"strings"
)
// Content represents the content part of a file.
//
// Content does NOT map to anything in Go's built-in "fs" package.
//
// But, for example, is used to create a RegularFile (which maps to a fs.File).
//
// Example usage:
//
// var content strfs.Content = strfs.CreateContent("<!DOCTYPE html>"+"\n"+"<html></html>")
//
// var regularfile strfs.RegularFile = strfs.RegularFile{
// FileContent: content,
// FileName: "notice.html",
// FileModTIme: time.Date(2022, 12, 12, 10, 30, 14, 2, time.UTC),
// }
type Content struct{
reader io.Reader
size int64
closed bool
}
// A trick to make sure strfs.Content fits the io.ReadCloser interface.
// This is a compile-time check.
var _ io.ReadCloser = &Content{}
// CreateContent returns a strfs.Content whose content is the string given to it.
//
// Example usage:
//
// var content strfs.Content = strfs.CreateContent("# Hello world!"+"\r\r"+"Welcome to my document."+"\n")
//
// var regularfile strfs.RegularFile = strfs.RegularFile{
// FileContent: content,
// FileName: "message.md",
// FileModTIme: time.Now(),
// }
func CreateContent(s string) Content {
var reader io.Reader = strings.NewReader(s)
var size int64 = int64(len(s))
return Content{
reader:reader,
size:size,
}
}
2022-12-14 11:10:01 +00:00
// EmptyContent is used to see if a given strfs.Content is empty.
2022-12-14 11:03:30 +00:00
//
2022-12-14 11:10:01 +00:00
// Note that a strfs.Content being empty is NOT the same as containing the empty string!
2022-12-14 11:03:30 +00:00
//
2022-12-14 11:10:01 +00:00
// A strfs.Content is empty when it hasn't been initialized.
2022-12-14 11:03:30 +00:00
//
// Example usage:
//
// var content strfs.Content
//
// // ...
//
2022-12-14 11:10:01 +00:00
// if strfs.EmptyContent() == content {
2022-12-14 11:03:30 +00:00
// //@TODO
// }
2022-12-14 11:10:01 +00:00
func EmptyContent() Content {
2022-12-14 11:03:30 +00:00
return Content{}
}
// Call close will stop the Read method from working.
//
// Close can safely be called more than once.
2022-12-14 11:43:11 +00:00
//
// Close makes strfs.Content fit the io.Closer interface.
2022-12-14 11:03:30 +00:00
func (receiver *Content) Close() error {
if nil == receiver {
return errNilReceiver
}
2022-12-14 11:14:48 +00:00
if receiver.Closed() {
2022-12-14 11:03:30 +00:00
return nil
}
receiver.closed = true
return nil
}
// Closed returns whether a strfs.Content is closed or not.
func (receiver *Content) Closed() bool {
if nil == receiver {
return true
}
2022-12-14 11:14:48 +00:00
if EmptyContent() == *receiver {
return true
}
2022-12-14 11:03:30 +00:00
return receiver.closed
}
2022-12-14 11:44:40 +00:00
2022-12-14 11:03:30 +00:00
// Read reads up to len(p) bytes into 'p'.
// Read returns the number of bytes actually read, and any errors it encountered.
//
2022-12-14 11:44:40 +00:00
// Read makes strfs.Content fit the io.Reader interface.
//
2022-12-14 11:03:30 +00:00
// Example usage:
//
// var content strfs.Content = strfs.CreateContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
//
// var b1 [5]byte
// var p1 []byte = b1[:]
//
// n, err := content.Read(p1)
//
// // n == 5
// // b1 == [5]byte{'A', 'B', 'C', 'D', 'E'}
//
// // ...
//
// var b2 [4]byte
// var p2 []byte = b2[:]
//
// n, err := content.Read(p2)
//
// // n == 4
// // b2 == [5]byte{'F', 'G', 'H', 'I'}
func (receiver *Content) Read(p []byte) (int, error) {
if nil == receiver {
return 0, errNilReceiver
}
if nil == p {
return 0, errNilByteSlice
}
2022-12-14 11:28:12 +00:00
if receiver.Closed() {
return 0, errClosed
}
2022-12-14 11:03:30 +00:00
var reader io.Reader = receiver.reader
if nil == reader {
return 0, errInternalError
}
return receiver.reader.Read(p)
}
// Size returns the of the strnig given to it as the number of bytes.
func (receiver *Content) Size() int64 {
if nil == receiver {
return 0
}
return receiver.size
}