-
Notifications
You must be signed in to change notification settings - Fork 16
/
copy.go
86 lines (72 loc) · 2.39 KB
/
copy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package section
import (
"encoding/binary"
"io"
"github.com/tsavola/wag/internal/errorpanic"
"github.com/tsavola/wag/internal/loader"
"github.com/tsavola/wag/internal/reader"
"github.com/tsavola/wag/internal/section"
)
// CopyStandardSection with the given type if one is found. The returned
// length includes the copied section's header and payload (everything that was
// written). Custom sections preceding the standard section are processed by
// customLoader (or discarded if it's nil) - they are not included in the
// returned length. If another standard section type is found, it is left
// untouched (the reader will be backed up before the section id) and zero
// length is returned. If no standard section is encountered, zero length and
// io.EOF are returned. io.EOF is returned only when it occurs between
// sections.
func CopyStandardSection(w io.Writer, r reader.R, id ID, customLoader func(r Reader, payloadLen uint32) error) (length int64, err error) {
defer func() {
if x := recover(); x != nil {
err = errorpanic.Handle(x)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
}
}()
load := loader.L{R: r}
switch section.Find(id, load, nil, customLoader) {
case id:
length, err = copySection(w, id, load)
case 0:
err = io.EOF
}
return
}
// SkipCustomSections until the next standard section. The skipped sections
// are processed by customLoader (or discarded if it's nil). If no standard
// section is encountered, io.EOF is returned. io.EOF is returned only when it
// occurs between sections.
func SkipCustomSections(r reader.R, customLoader func(Reader, uint32) error) (err error) {
defer func() {
if x := recover(); x != nil {
err = errorpanic.Handle(x)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
}
}()
load := loader.L{R: r}
if section.Find(0, load, nil, customLoader) == 0 {
err = io.EOF
}
return
}
func copySection(w io.Writer, id ID, load loader.L) (length int64, err error) {
payloadLen := load.Varuint32()
head := make([]byte, 1+binary.MaxVarintLen32)
head[0] = byte(id)
n := binary.PutUvarint(head[1:], uint64(payloadLen))
n, err = w.Write(head[:1+n])
length += int64(n)
if err != nil {
return
}
m, err := io.CopyN(w, load.R, int64(payloadLen))
length += m
return
}