av/stream/mts/meta.go

146 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
NAME
meta.go
DESCRIPTION
See Readme.md
AUTHOR
Saxon Nelson-Milton <saxon@ausocean.org>
LICENSE
meta.go is Copyright (C) 2017-2019 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
*/
package mts
import (
"errors"
"strings"
"sync"
)
const headSize = 4
const (
majVer = 1
minVer = 0
)
const (
dataLenIdx1 = 2
dataLenIdx2 = 3
)
var (
errKeyAbsent = errors.New("Key does not exist in map")
)
type Metadata struct {
mu sync.RWMutex
data map[string]string
enc []byte
}
func NewMeta() *Metadata {
return &Metadata{
data: make(map[string]string),
enc: []byte{
0x00, // Reserved byte
(majVer << 4) | minVer, // MS and LS versions
0x00, // Data len byte1
0x00, // Data len byte2
},
}
}
// Add adds metadata with key and val, if already exists return error
func (m *Metadata) Add(key, val string) {
m.mu.Lock()
m.data[key] = val
m.mu.Unlock()
}
// All returns the a copy of the map containing the meta data
func (m *Metadata) All() map[string]string {
m.mu.Lock()
cpy := make(map[string]string)
for k, v := range m.data {
cpy[k] = v
}
m.mu.Unlock()
return cpy
}
// Get returns the meta data for the passed key
func (m *Metadata) Get(key string) (string, error) {
m.mu.Lock()
val, ok := m.data[key]
m.mu.Unlock()
if !ok {
return "", errKeyAbsent
}
return val, nil
}
// Remove deletes a meta entry in the map and returns error if it doesnt exist
func (m *Metadata) Delete(key string) error {
m.mu.Lock()
defer m.mu.Unlock()
if _, ok := m.data[key]; ok {
delete(m.data, key)
return nil
}
return errKeyAbsent
}
// Encode takes the meta data map and encods into a byte slice with header
// describing the version, length of data and data in TSV format.
func (m *Metadata) Encode() []byte {
m.enc = m.enc[:headSize]
// Iterate over map and append entries, only adding tab if we're not on the last entry
var i int
var entry string
for k, v := range m.data {
i++
entry += k + "=" + v
if i < len(m.data) {
entry += "\t"
}
}
m.enc = append(m.enc, []byte(entry)...)
// Calculate and set data length in encoded meta header.
dataLen := len(m.enc[headSize:])
m.enc[dataLenIdx1] = byte(dataLen >> 8)
m.enc[dataLenIdx2] = byte(dataLen)
return m.enc
}
func ReadFrom(d []byte, key string) (string, error) {
entries := strings.Split(string(d), "\t")
for _, entry := range entries {
kv := strings.Split(entry, "=")
if kv[0] == key {
return kv[1], nil
}
}
return "", errors.New("could not find key in metadata")
}