github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/mediatype/media-type.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package mediatype
     4  
     5  import (
     6  	"encoding/base64"
     7  	"reflect"
     8  	"strings"
     9  	"unsafe"
    10  
    11  	"golang.org/x/crypto/sha3"
    12  
    13  	"../protocol"
    14  	"../time/unix"
    15  )
    16  
    17  // MediaType implement protocol.MediaType interface
    18  // type "/" [tree "."] subtype ["+" suffix]* [";" parameter]
    19  // https://datatracker.ietf.org/doc/html/rfc2046
    20  type MediaType struct {
    21  	uuid       [32]byte
    22  	id         uint64
    23  	idAsString string
    24  
    25  	mediaType  string
    26  	mainType   string
    27  	tree       string
    28  	subType    string
    29  	suffix     string
    30  	parameters []string
    31  
    32  	fileExtension string
    33  
    34  	referenceURI    string
    35  	status          protocol.SoftwareStatus
    36  	issueDate       unix.Time
    37  	expiryDate      unix.Time
    38  	expireInFavorOf protocol.MediaType // Other MediaType
    39  
    40  	detail  map[protocol.LanguageID]*MediaTypeDetail
    41  	details []protocol.MediaTypeDetail
    42  
    43  	fields []protocol.Field
    44  }
    45  
    46  func (mt *MediaType) Init(mediatype string) {
    47  	mt.mediaType = mediatype
    48  
    49  	// TODO::: complete extraction
    50  	var i = strings.IndexByte(mediatype, '/')
    51  	mt.mainType = mediatype[:i]
    52  	mt.subType = mediatype[i+1:]
    53  
    54  	mt.uuid, mt.id = IDGenerator(mediatype)
    55  	mt.idAsString = base64.RawURLEncoding.EncodeToString(mt.uuid[:8])
    56  
    57  	mt.detail = map[protocol.LanguageID]*MediaTypeDetail{}
    58  }
    59  
    60  func (mt *MediaType) RegisterMediaType() {
    61  	// Check due to os can be nil almost in tests and benchmarks build
    62  	if protocol.OS != nil {
    63  		protocol.OS.RegisterMediaType(mt)
    64  	}
    65  }
    66  
    67  func (mt *MediaType) UUID() [32]byte                      { return mt.uuid }
    68  func (mt *MediaType) ID() uint64                          { return mt.id }
    69  func (mt *MediaType) IDasString() string                  { return mt.idAsString }
    70  func (mt *MediaType) MainType() string                    { return mt.mainType }
    71  func (mt *MediaType) Tree() string                        { return mt.tree }
    72  func (mt *MediaType) SubType() string                     { return mt.subType }
    73  func (mt *MediaType) Suffix() string                      { return mt.suffix }
    74  func (mt *MediaType) Parameters() []string                { return mt.parameters }
    75  func (mt *MediaType) FileExtension() string               { return mt.fileExtension }
    76  func (mt *MediaType) Status() protocol.SoftwareStatus     { return mt.status }
    77  func (mt *MediaType) IssueDate() protocol.Time            { return &mt.issueDate }
    78  func (mt *MediaType) ExpiryDate() protocol.Time           { return &mt.expiryDate }
    79  func (mt *MediaType) ExpireInFavorOf() protocol.MediaType { return mt.expireInFavorOf }
    80  func (mt *MediaType) Details() []protocol.MediaTypeDetail { return mt.details }
    81  func (mt *MediaType) Detail(lang protocol.LanguageID) protocol.MediaTypeDetail {
    82  	return mt.detail[lang]
    83  }
    84  func (mt *MediaType) Fields() []protocol.Field { return mt.fields }
    85  func (mt *MediaType) ToString() string         { return mt.mediaType }
    86  
    87  func (mt *MediaType) SetFileExtension(fileExtension string) {
    88  	mt.fileExtension = fileExtension
    89  	// TODO::: if application use other package to register mediatypes, below logic will break the app functionality.
    90  	poolByFileExtension[fileExtension] = mt
    91  	// protocol.OS.RegisterMediaType(mt)
    92  }
    93  
    94  func (mt *MediaType) SetInfo(status protocol.SoftwareStatus, issueDate unix.SecElapsed, referenceURI string) {
    95  	mt.status = status
    96  	mt.issueDate.ChangeTo(issueDate, 0)
    97  	mt.referenceURI = referenceURI
    98  }
    99  
   100  // SetDetail add error text details to existing error and return it.
   101  func (mt *MediaType) SetDetail(lang protocol.LanguageID, domain, summary, overview, userNote, devNote string, tags []string) {
   102  	var _, ok = mt.detail[lang]
   103  	if ok {
   104  		panic("Can't change MediaType detail after first set! Ask the holder to change details.")
   105  	}
   106  
   107  	var detail = MediaTypeDetail{
   108  		languageID: lang,
   109  		domain:     domain,
   110  		summary:    summary,
   111  		overview:   overview,
   112  		userNote:   userNote,
   113  		devNote:    devNote,
   114  		tags:       tags,
   115  	}
   116  	mt.detail[lang] = &detail
   117  	mt.details = append(mt.details, &detail)
   118  }
   119  
   120  func (mt *MediaType) Expired(expiryDate unix.Time, inFavorOf protocol.MediaType) {
   121  	mt.expiryDate = expiryDate
   122  	mt.expireInFavorOf = inFavorOf
   123  }
   124  
   125  func IDGenerator(uri string) (uuid [32]byte, id uint64) {
   126  	uuid = sha3.Sum256(unsafeStringToByteSlice(uri))
   127  	id = uint64(uuid[0]) | uint64(uuid[1])<<8 | uint64(uuid[2])<<16 | uint64(uuid[3])<<24 | uint64(uuid[4])<<32 | uint64(uuid[5])<<40 | uint64(uuid[6])<<48 | uint64(uuid[7])<<56
   128  	return
   129  }
   130  
   131  func IDfromString(IDasString string) (id uint64, err protocol.Error) {
   132  	var IDasSlice = unsafeStringToByteSlice(IDasString)
   133  	var ID [8]byte
   134  	var _, goErr = base64.RawURLEncoding.Decode(ID[:], IDasSlice)
   135  	if goErr != nil {
   136  		// err =
   137  		return
   138  	}
   139  	id = uint64(ID[0]) | uint64(ID[1])<<8 | uint64(ID[2])<<16 | uint64(ID[3])<<24 | uint64(ID[4])<<32 | uint64(ID[5])<<40 | uint64(ID[6])<<48 | uint64(ID[7])<<56
   140  	return
   141  }
   142  
   143  func unsafeStringToByteSlice(req string) (res []byte) {
   144  	var reqStruct = (*reflect.StringHeader)(unsafe.Pointer(&req))
   145  	var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
   146  	resStruct.Data = reqStruct.Data
   147  	resStruct.Len = reqStruct.Len
   148  	resStruct.Cap = reqStruct.Len
   149  	return
   150  }