package treeificator import ( "strings" "git.mstar.dev/mstar/goutils/other" ) func Marshal(raw string, informers ...Informer) Node { prefixToInformer := map[string]Informer{} maxPrefixLen := 0 for _, informer := range informers { prefixToInformer[informer.GetPrefix()] = informer if l := len(informer.GetPrefix()); l > maxPrefixLen { maxPrefixLen = l } } defaultInformer := &DefaultInformer{} delete(prefixToInformer, defaultInformer.GetPrefix()) elems, consumed := marshal(raw, prefixToInformer, nil) _ = consumed return Node{ NodeType: defaultInformer, Elements: elems, } } // Return the elements in the given string, using the given informers, in order of appearance. func marshal( raw string, informers map[string]Informer, activeInformer Informer, ) ([]NodeElement, uint64) { elements := []NodeElement{} buffer := make([]rune, 0) var consumed uint64 = 0 var insideDiff uint64 = 0 // Nr of runes consumed by recursive calls outer: for i, char := range []rune(raw) { i++ // Skip runes that have been consumed by recursive calls if uint64(i) < consumed { continue } buffer = append(buffer, char) consumed = uint64(i) for k, v := range informers { if !strings.HasSuffix(string(buffer), k) { continue } if len(buffer) > 0 { // Cut informer prefix from buffer, append buffer as text element elements = append( elements, NodeElement{Text: other.IntoPointer(strings.TrimSuffix(string(buffer), k))}, ) } buffer = make([]rune, 0) subElems, subConsumed := marshal(string([]rune(raw)[consumed:]), informers, v) elements = append(elements, NodeElement{ Node: &Node{ NodeType: v, Elements: subElems, }, }) insideDiff += subConsumed consumed += subConsumed continue outer } if activeInformer != nil && strings.HasSuffix(string(buffer), activeInformer.GetSuffix()) { if len(buffer) > 0 { b := strings.TrimSuffix(string(buffer), activeInformer.GetSuffix()) elements = append( elements, NodeElement{ Text: other.IntoPointer( b, ), }, ) } return elements, uint64(consumed) + 1 } } if len(buffer) > 0 { elements = append(elements, NodeElement{Text: other.IntoPointer(string(buffer))}) } return elements, uint64(consumed) }