go-hep.org/x/hep@v0.38.1/fwk/hbooksvc/stream.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hbooksvc 6 7 import ( 8 "fmt" 9 "io" 10 "os" 11 12 "go-hep.org/x/hep/fwk" 13 "go-hep.org/x/hep/rio" 14 ) 15 16 // Mode describes the open-mode of a stream 17 type Mode int 18 19 const ( 20 Read Mode = Mode(os.O_RDONLY) 21 Write Mode = Mode(os.O_WRONLY) 22 ) 23 24 // Stream defines an input or output hbook stream 25 type Stream struct { 26 Name string // input|output file name 27 Mode Mode // read|write 28 } 29 30 type istream struct { 31 name string // stream name 32 fname string // file name 33 f io.ReadCloser 34 r *rio.Reader 35 objs []fwk.Hist 36 } 37 38 func (stream *istream) close() error { 39 defer stream.f.Close() // do not leak file descriptors 40 err := stream.r.Close() 41 if err != nil { 42 return err 43 } 44 45 err = stream.f.Close() 46 if err != nil { 47 return err 48 } 49 50 return err 51 } 52 53 func (stream *istream) read(name string, ptr any) error { 54 var err error 55 56 seekr, ok := stream.f.(io.Seeker) 57 if !ok { 58 return fmt.Errorf("hbooksvc: input stream [%s] is not seek-able", stream.name) 59 } 60 61 pos, err := seekr.Seek(0, 1) 62 if err != nil { 63 return err 64 } 65 defer func() { 66 _, _ = seekr.Seek(pos, 0) 67 }() 68 69 _, err = seekr.Seek(0, 0) 70 if err != nil { 71 return err 72 } 73 74 r := seekr.(io.Reader) 75 rr, err := rio.NewReader(r) 76 if err != nil { 77 return err 78 } 79 defer rr.Close() 80 81 scan := rio.NewScanner(rr) 82 scan.Select([]rio.Selector{{Name: name, Unpack: true}}) 83 if !scan.Scan() { 84 return scan.Err() 85 } 86 rec := scan.Record() 87 if rec == nil { 88 return fmt.Errorf("hbooksvc: could not find record [%s] in stream [%s]", name, stream.name) 89 } 90 blk := rec.Block(name) 91 if blk == nil { 92 return fmt.Errorf( 93 "hbooksvc: could not get block [%s] from record [%s] in stream [%s]", 94 name, name, stream.name, 95 ) 96 } 97 err = blk.Read(ptr) 98 if err != nil { 99 return fmt.Errorf( 100 "hbooksvc: could not read data from block [%s] from record [%s] in stream [%s]: %w", 101 name, name, stream.name, err, 102 ) 103 } 104 return err 105 } 106 107 type ostream struct { 108 name string // stream name 109 fname string // file name 110 f io.WriteCloser 111 w *rio.Writer 112 objs []fwk.Hist 113 } 114 115 func (stream *ostream) write() error { 116 for i := range stream.objs { 117 obj := stream.objs[i] 118 name := string(obj.Name()) 119 rec := stream.w.Record(name) 120 err := rec.Connect(name, obj.Value()) 121 if err != nil { 122 return fmt.Errorf( 123 "error writing object [%s] to stream [%s]: %w", 124 name, stream.name, err, 125 ) 126 } 127 128 blk := rec.Block(name) 129 err = blk.Write(obj.Value()) 130 if err != nil { 131 return fmt.Errorf( 132 "error writing object [%s] to stream [%s]: %w", 133 name, stream.name, err, 134 ) 135 } 136 137 err = rec.Write() 138 if err != nil { 139 return fmt.Errorf( 140 "error writing object [%s] to stream [%s]: %w", 141 name, stream.name, err, 142 ) 143 } 144 } 145 146 return nil 147 } 148 149 func (stream *ostream) close() error { 150 defer stream.f.Close() // do not leak file descriptors 151 err := stream.w.Close() 152 if err != nil { 153 return err 154 } 155 156 err = stream.f.Close() 157 if err != nil { 158 return err 159 } 160 161 return err 162 }