about summary refs log tree commit diff stats
path: root/worker/types/thread.go
diff options
context:
space:
mode:
Diffstat (limited to 'worker/types/thread.go')
-rw-r--r--worker/types/thread.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/worker/types/thread.go b/worker/types/thread.go
new file mode 100644
index 0000000..09f9dbb
--- /dev/null
+++ b/worker/types/thread.go
@@ -0,0 +1,99 @@
+package types
+
+import (
+	"errors"
+	"fmt"
+)
+
+type Thread struct {
+	Uid         uint32
+	Parent      *Thread
+	PrevSibling *Thread
+	NextSibling *Thread
+	FirstChild  *Thread
+
+	Hidden  bool // if this flag is set the message isn't rendered in the UI
+	Deleted bool // if this flag is set the message was deleted
+}
+
+func (t *Thread) Walk(walkFn NewThreadWalkFn) error {
+	err := newWalk(t, walkFn, 0, nil)
+	if err == ErrSkipThread {
+		return nil
+	}
+	return err
+}
+
+func (t *Thread) String() string {
+	if t == nil {
+		return "<nil>"
+	}
+	parent := -1
+	if t.Parent != nil {
+		parent = int(t.Parent.Uid)
+	}
+	next := -1
+	if t.NextSibling != nil {
+		next = int(t.NextSibling.Uid)
+	}
+	child := -1
+	if t.FirstChild != nil {
+		child = int(t.FirstChild.Uid)
+	}
+	return fmt.Sprintf(
+		"[%d] (parent:%v, next:%v, child:%v)",
+		t.Uid, parent, next, child,
+	)
+}
+
+func newWalk(node *Thread, walkFn NewThreadWalkFn, lvl int, ce error) error {
+	if node == nil {
+		return nil
+	}
+	err := walkFn(node, lvl, ce)
+	if err != nil {
+		return err
+	}
+	for child := node.FirstChild; child != nil; child = child.NextSibling {
+		err = newWalk(child, walkFn, lvl+1, err)
+		if err == ErrSkipThread {
+			err = nil
+			continue
+		} else if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+var ErrSkipThread = errors.New("skip this Thread")
+
+type NewThreadWalkFn func(t *Thread, level int, currentErr error) error
+
+//Implement interface to be able to sort threads by newest (max UID)
+type ByUID []*Thread
+
+func getMaxUID(thread *Thread) uint32 {
+	// TODO: should we make this part of the Thread type to avoid recomputation?
+	var Uid uint32
+
+	thread.Walk(func(t *Thread, _ int, currentErr error) error {
+		if t.Uid > Uid {
+			Uid = t.Uid
+		}
+		return nil
+	})
+	return Uid
+}
+
+func (s ByUID) Len() int {
+	return len(s)
+}
+func (s ByUID) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+func (s ByUID) Less(i, j int) bool {
+	maxUID_i := getMaxUID(s[i])
+	maxUID_j := getMaxUID(s[j])
+	return maxUID_i < maxUID_j
+}