diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..30bab2a
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/go-extypes.iml b/.idea/go-extypes.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/go-extypes.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..967f534
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..417315f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..1c06bd7
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,9 @@
+
+
+ {
+ "keyToString": {
+ "go.import.settings.migrated": "true",
+ "settings.editor.selected.configurable": "preferences.pluginManager"
+ }
+}
+
\ No newline at end of file
diff --git a/map.go b/map.go
new file mode 100644
index 0000000..0509887
--- /dev/null
+++ b/map.go
@@ -0,0 +1,46 @@
+package laniakea
+
+type HashMap[K comparable, V any] map[K]V
+
+func NewMapFrom[K comparable, V any](m map[K]V) HashMap[K, V] {
+ out := make(HashMap[K, V])
+ for k, v := range m {
+ out[k] = v
+ }
+ return out
+}
+func (m HashMap[K, V]) Len() int {
+ return len(m)
+}
+func (m HashMap[K, V]) Add(key K, val V) HashMap[K, V] {
+ m[key] = val
+ return m
+}
+func (m HashMap[K, V]) Remove(key K) HashMap[K, V] {
+ delete(m, key)
+ return m
+}
+func (m HashMap[K, V]) Get(key K) V {
+ return m[key]
+}
+func (m HashMap[K, V]) GetOrDefault(key K, def V) V {
+ v, ok := m[key]
+ if !ok {
+ return def
+ }
+ return v
+}
+func (m HashMap[K, V]) Contains(key K) bool {
+ _, ok := m[key]
+ return ok
+}
+func (m HashMap[K, V]) Filter(f func(K, V) bool) HashMap[K, V] {
+ out := make(HashMap[K, V])
+ for k, v := range m {
+ if !f(k, v) {
+ continue
+ }
+ out[k] = v
+ }
+ return out
+}
diff --git a/queue.go b/queue.go
new file mode 100644
index 0000000..d319ce7
--- /dev/null
+++ b/queue.go
@@ -0,0 +1,71 @@
+package laniakea
+
+import (
+ "errors"
+ "sync"
+)
+
+var QueueFullErr = errors.New("queue full")
+
+type Queue[T any] struct {
+ size uint64
+ mu sync.RWMutex
+ queue []T
+}
+
+func CreateQueue[T any](size uint64) *Queue[T] {
+ return &Queue[T]{
+ queue: make([]T, 0),
+ size: size,
+ }
+}
+
+func (q *Queue[T]) Enqueue(el T) error {
+ if q.IsFull() {
+ return QueueFullErr
+ }
+ q.queue = append(q.queue, el)
+ return nil
+}
+
+func (q *Queue[T]) Peak() T {
+ q.mu.RLock()
+ defer q.mu.RUnlock()
+ return q.queue[0]
+}
+
+func (q *Queue[T]) IsEmpty() bool {
+ return q.Length() == 0
+}
+
+func (q *Queue[T]) IsFull() bool {
+ return q.Length() == q.size
+}
+
+func (q *Queue[T]) Length() uint64 {
+ q.mu.RLock()
+ defer q.mu.RUnlock()
+ return uint64(len(q.queue))
+}
+
+func (q *Queue[T]) Dequeue() T {
+ q.mu.RLock()
+ el := q.queue[0]
+ q.mu.RUnlock()
+
+ if q.Length() == 1 {
+ q.mu.Lock()
+ q.queue = make([]T, 0)
+ q.mu.Unlock()
+ return el
+ }
+
+ q.mu.Lock()
+ q.queue = q.queue[1:]
+ q.mu.Unlock()
+ return el
+}
+
+func (q *Queue[T]) Raw() []T {
+ return q.queue
+}
diff --git a/slice.go b/slice.go
new file mode 100644
index 0000000..aa88a57
--- /dev/null
+++ b/slice.go
@@ -0,0 +1,176 @@
+package laniakea
+
+import "slices"
+
+type Slice[T comparable] []T
+
+func NewSliceFrom[T comparable](slice []T) Slice[T] {
+ s := make(Slice[T], len(slice))
+ copy(s, slice)
+ return s
+}
+func (s Slice[T]) Len() int {
+ return len(s)
+}
+func (s Slice[T]) Cap() int {
+ return cap(s)
+}
+func (s Slice[T]) Get(index int) T {
+ return s[index]
+}
+func (s Slice[T]) Last() T {
+ return s.Get(s.Len() - 1)
+}
+func (s Slice[T]) Index(el T) int {
+ return slices.Index(s, el)
+}
+
+// Swap is mutable func
+func (s Slice[T]) Swap(i, j int) Slice[T] {
+ s[i], s[j] = s[j], s[i]
+ return s
+}
+func (s Slice[T]) Filter(f func(e T) bool) Slice[T] {
+ out := make(Slice[T], 0)
+ for _, v := range s {
+ if f(v) {
+ out = append(out, v)
+ }
+ }
+ return out
+}
+func (s Slice[T]) Map(f func(e T) T) Slice[T] {
+ out := make(Slice[T], s.Len())
+ for i, v := range s {
+ out[i] = f(v)
+ }
+ return out
+}
+func (s Slice[T]) Pop(index int) Slice[T] {
+ if index == 0 {
+ return s[1:]
+ }
+ out := make(Slice[T], s.Len()-index)
+ for i, e := range s {
+ if i == index {
+ continue
+ }
+ out[i] = e
+ }
+ return out
+}
+func (s Slice[T]) Remove(el T) Slice[T] {
+ index := s.Index(el)
+ if index == -1 {
+ return s
+ }
+ return s.Pop(index)
+}
+func (s Slice[T]) Push(e T) Slice[T] {
+ return append(s, e)
+}
+
+func (s Slice[T]) ToArray() []T {
+ out := make([]T, len(s))
+ copy(out, s)
+ return out
+}
+func (s Slice[T]) ToAnyArray() []any {
+ out := make([]any, len(s))
+ for i, v := range s {
+ out[i] = v
+ }
+ return out
+}
+
+// ForEach is mutable func
+func (s Slice[T]) ForEach(f func(e T) T) Slice[T] {
+ for i, v := range s {
+ s[i] = f(v)
+ }
+ return s
+}
+
+type Set[T comparable] []T
+
+func NewSetFrom[T comparable](slice []T) Set[T] {
+ s := make(Set[T], 0)
+ for _, v := range slice {
+ if s.Index(v) >= 0 {
+ continue
+ }
+ s = append(s, v)
+ }
+ return s
+}
+func (s Set[T]) Len() int {
+ return len(s)
+}
+func (s Set[T]) Cap() int {
+ return cap(s)
+}
+func (s Set[T]) Get(index int) T {
+ return s[index]
+}
+func (s Set[T]) Last() T {
+ return s[s.Len()-1]
+}
+func (s Set[T]) Index(el T) int {
+ return slices.Index(s, el)
+}
+func (s Set[T]) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s Set[T]) Add(v T) Set[T] {
+ index := s.Index(v)
+ if index >= 0 {
+ return s
+ }
+ return append(s, v)
+}
+func (s Set[T]) Pop(index int) Set[T] {
+ if index == 0 {
+ return s[1:]
+ }
+ out := make(Set[T], s.Len()-index)
+ for i, e := range s {
+ if i == index {
+ continue
+ }
+ out[i] = e
+ }
+ return out
+}
+func (s Set[T]) Remove(el T) Set[T] {
+ index := s.Index(el)
+ if index == -1 {
+ return s
+ }
+ return s.Pop(index)
+}
+func (s Set[T]) Filter(f func(e T) bool) Set[T] {
+ out := make(Set[T], 0)
+ for _, v := range s {
+ if f(v) {
+ out = append(out, v)
+ }
+ }
+ return out
+}
+func (s Set[T]) ToSlice() Slice[T] {
+ out := make(Slice[T], s.Len())
+ copy(out, s)
+ return out
+}
+func (s Set[T]) ToArray() []T {
+ out := make([]T, len(s))
+ copy(out, s)
+ return out
+}
+func (s Set[T]) ToAnyArray() []any {
+ out := make([]any, len(s))
+ for i, v := range s {
+ out[i] = v
+ }
+ return out
+}