forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at master 1.8 kB view raw
1package models 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7 "strings" 8 "time" 9 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 "tangled.org/core/api/tangled" 12) 13 14type String struct { 15 Did syntax.DID 16 Rkey string 17 18 Filename string 19 Description string 20 Contents string 21 Created time.Time 22 Edited *time.Time 23} 24 25func (s *String) AtUri() syntax.ATURI { 26 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", s.Did, tangled.StringNSID, s.Rkey)) 27} 28 29func (s *String) AsRecord() tangled.String { 30 return tangled.String{ 31 Filename: s.Filename, 32 Description: s.Description, 33 Contents: s.Contents, 34 CreatedAt: s.Created.Format(time.RFC3339), 35 } 36} 37 38func StringFromRecord(did, rkey string, record tangled.String) String { 39 created, err := time.Parse(record.CreatedAt, time.RFC3339) 40 if err != nil { 41 created = time.Now() 42 } 43 return String{ 44 Did: syntax.DID(did), 45 Rkey: rkey, 46 Filename: record.Filename, 47 Description: record.Description, 48 Contents: record.Contents, 49 Created: created, 50 } 51} 52 53type StringStats struct { 54 LineCount uint64 55 ByteCount uint64 56} 57 58func (s String) Stats() StringStats { 59 lineCount, err := countLines(strings.NewReader(s.Contents)) 60 if err != nil { 61 // non-fatal 62 // TODO: log this? 63 } 64 65 return StringStats{ 66 LineCount: uint64(lineCount), 67 ByteCount: uint64(len(s.Contents)), 68 } 69} 70 71func countLines(r io.Reader) (int, error) { 72 buf := make([]byte, 32*1024) 73 bufLen := 0 74 count := 0 75 nl := []byte{'\n'} 76 77 for { 78 c, err := r.Read(buf) 79 if c > 0 { 80 bufLen += c 81 } 82 count += bytes.Count(buf[:c], nl) 83 84 switch { 85 case err == io.EOF: 86 /* handle last line not having a newline at the end */ 87 if bufLen >= 1 && buf[(bufLen-1)%(32*1024)] != '\n' { 88 count++ 89 } 90 return count, nil 91 case err != nil: 92 return 0, err 93 } 94 } 95}