github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/bas/io.go (about) 1 package bas 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io" 8 "strings" 9 10 "github.com/coyove/nj/typ" 11 ) 12 13 type valueIO Value 14 15 // Reader creates an io.Reader from value, Read() may fail if value doesn't support reading. 16 func (v Value) Reader() io.Reader { 17 switch rd := v.Interface().(type) { 18 case io.Reader: 19 return rd 20 case []byte: 21 return bytes.NewReader(rd) 22 case string: 23 return strings.NewReader(v.Str()) 24 } 25 return valueIO(v) 26 } 27 28 // Writer creates an io.Writer from value, Write() may fail if value doesn't support writing. 29 func (v Value) Writer() io.Writer { 30 switch rd := v.Interface().(type) { 31 case io.Writer: 32 return rd 33 case []byte: 34 w := bytes.NewBuffer(rd) 35 w.Reset() 36 return w 37 } 38 return valueIO(v) 39 } 40 41 // Closer creates an io.Closer from value, Close() may fail if value doesn't support closing. 42 func (v Value) Closer() io.Closer { 43 if rd, ok := v.Interface().(io.Closer); ok { 44 return rd 45 } 46 return valueIO(v) 47 } 48 49 func (m valueIO) Read(p []byte) (int, error) { 50 switch Value(m).Type() { 51 case typ.Native: 52 if rd, _ := Value(m).Interface().(io.Reader); rd != nil { 53 return rd.Read(p) 54 } 55 case typ.Object: 56 if rb := Value(m).Object().Get(Str("read2")); rb.IsObject() { 57 t := rb.Object().Call(nil, Bytes(p)).AssertShape("(i, EN)", "Reader.read2").Native() 58 if t.Get(1).IsError() { 59 return t.Get(0).Int(), t.Get(1).Error() 60 } 61 return t.Get(0).Int(), nil 62 } 63 if rb := Value(m).Object().Get(Str("read")); rb.IsObject() { 64 switch v := rb.Object().Call(nil, Int(len(p))); v.Type() { 65 case typ.Nil: 66 return 0, io.EOF 67 case typ.String: 68 return copy(p, v.Str()), nil 69 case typ.Native: 70 return copy(p, v.AssertShape("sB", "Reader.read").Native().Unwrap().([]byte)), nil 71 default: 72 v.AssertShape("sB", "Reader.read") 73 } 74 } 75 } 76 return 0, fmt.Errorf("reader not implemented") 77 } 78 79 func (m valueIO) WriteString(p string) (int, error) { 80 return m.Write([]byte(p)) 81 } 82 83 func (m valueIO) Write(p []byte) (int, error) { 84 switch Value(m).Type() { 85 case typ.Native: 86 if rd, _ := Value(m).Interface().(io.Writer); rd != nil { 87 return rd.Write(p) 88 } 89 case typ.Object: 90 if rb := Value(m).Object().Get(Str("write")); rb.IsObject() { 91 v := rb.Object().Call(nil, Bytes(p)) 92 if v.IsError() { 93 return 0, v.Error() 94 } 95 return v.AssertNumber("Writer.write").Int(), nil 96 } 97 if rb := Value(m).Object().Get(Str("write2")); rb.IsObject() { 98 t := rb.Object().Call(nil, Bytes(p)).AssertShape("(i, EN)", "Writer.write2").Native() 99 if t.Get(1).IsError() { 100 return t.Get(0).Int(), t.Get(1).Error() 101 } 102 return t.Get(0).Int(), nil 103 } 104 } 105 return 0, fmt.Errorf("writer not implemented") 106 } 107 108 func (m valueIO) Close() error { 109 switch Value(m).Type() { 110 case typ.Native: 111 if rd, _ := Value(m).Interface().(io.Closer); rd != nil { 112 return rd.Close() 113 } 114 case typ.Object: 115 if rb := Value(m).Object().Get(Str("close")); rb.IsObject() { 116 if v := rb.Object().Call(nil); v.IsError() { 117 return v.Error() 118 } 119 return nil 120 } 121 } 122 return fmt.Errorf("closer not implemented") 123 } 124 125 type ioReadlinesStruct struct { 126 rd *bufio.Reader 127 delim byte 128 bytes bool 129 }