matrix-capnproto-fed

What if Matrix was written using Cap'n'proto and a RPC federation API?
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-capnproto-fed.git
Log | Files | Refs | README | LICENSE

map_wrapper.go (2521B)


      1 package rpcserver
      2 
      3 import (
      4 	capnp "capnproto.org/go/capnp/v3"
      5 	protocol_types "github.com/MTRNord/matrix_protobuf_fed/proto/federation/v1/types"
      6 )
      7 
      8 /*
      9  * This is a wrapper for the Map capnproto type which is defined as:
     10  *
     11  * ```
     12  * # A generic map from keys to values.
     13  * struct Map(Key, Value) {
     14  *   entries @0 :List(Entry);
     15  *   struct Entry @0xb000b19244fa63f4 {
     16  *     key @0 :Key;
     17  *     value @1 :Value;
     18  *   }
     19  * }
     20  * ```
     21  *
     22  * Contrary to normal go maps this map has a fixed size.
     23  */
     24 type Map[Key capnp.Ptr, Value capnp.Ptr] struct {
     25 	internalMap *protocol_types.Map
     26 	maxSize     int32
     27 }
     28 
     29 // NewMap creates a new Map Wrapper
     30 func NewMap[Key capnp.Ptr, Value capnp.Ptr](s *capnp.Segment, maxSize int32) (*Map[Key, Value], error) {
     31 	internalMap, err := protocol_types.NewMap(s)
     32 	if err != nil {
     33 		return nil, err
     34 	}
     35 
     36 	return &Map[Key, Value]{
     37 		internalMap: &internalMap,
     38 		maxSize:     maxSize,
     39 	}, nil
     40 }
     41 
     42 // FromMap converts a capnp map to a wrapper
     43 func FromMap[Key capnp.Ptr, Value capnp.Ptr](m *protocol_types.Map, maxSize int32) *Map[Key, Value] {
     44 	return &Map[Key, Value]{
     45 		internalMap: m,
     46 		maxSize:     maxSize,
     47 	}
     48 }
     49 
     50 // HasEntries returns true if the map has entries
     51 func (m *Map[Key, Value]) HasEntries() bool {
     52 	return m.internalMap.HasEntries()
     53 }
     54 
     55 // Get a Segment of the internal map
     56 func (m *Map[Key, Value]) Segment() *capnp.Segment {
     57 	return m.internalMap.Segment()
     58 }
     59 
     60 // Entries returns the entries of the map as a go map
     61 func (m *Map[Key, Value]) Entries() (map[Key]*Value, error) {
     62 	// Check if we have entries. If not we return an empty map
     63 	result := make(map[Key]*Value)
     64 	if !m.HasEntries() {
     65 		return result, nil
     66 	}
     67 
     68 	entries, err := m.internalMap.Entries()
     69 	if err != nil {
     70 		return nil, err
     71 	}
     72 
     73 	for i := 0; i < entries.Len(); i++ {
     74 		entry := entries.At(i)
     75 		key, err := entry.Key()
     76 		if err != nil {
     77 			return nil, err
     78 		}
     79 
     80 		value_raw, err := entry.Value()
     81 		if err != nil {
     82 			return nil, err
     83 		}
     84 
     85 		value := Value(value_raw)
     86 		result[Key(key)] = &value
     87 	}
     88 
     89 	return result, nil
     90 }
     91 
     92 func (m *Map[Key, Value]) AddEntry(key Key, value Value) error {
     93 	// Check if we have any entries
     94 	if !m.internalMap.HasEntries() {
     95 		// Allocate enough entries
     96 		_, err := m.internalMap.NewEntries(m.maxSize)
     97 		if err != nil {
     98 			return err
     99 		}
    100 	}
    101 	internalEntries, err := m.internalMap.Entries()
    102 	if err != nil {
    103 		return err
    104 	}
    105 
    106 	entry := internalEntries.At(internalEntries.Len() - 1)
    107 	err = entry.SetKey(capnp.Ptr(key))
    108 	if err != nil {
    109 		return err
    110 	}
    111 	return entry.SetValue(capnp.Ptr(value))
    112 }