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 }