| 37 | } |
| 38 | |
| 39 | func (b *Build) Implementation() *Generator { |
| 40 | ifaces := b.Interfaces |
| 41 | // subIfaces has all interfaces except http.ResponseWriter |
| 42 | subIfaces := ifaces[1:] |
| 43 | |
| 44 | var g Generator |
| 45 | // Package header |
| 46 | b.writeHeader(&g) |
| 47 | g.Printf("import (\n") |
| 48 | g.Printf(`"net/http"` + "\n") |
| 49 | g.Printf(`"io"` + "\n") |
| 50 | g.Printf(`"net"` + "\n") |
| 51 | g.Printf(`"bufio"` + "\n") |
| 52 | g.Printf(`"time"` + "\n") |
| 53 | g.Printf(")\n") |
| 54 | g.Printf("\n") |
| 55 | |
| 56 | // Hook funcs |
| 57 | for _, iface := range ifaces { |
| 58 | for _, fn := range iface.Funcs { |
| 59 | g.Printf("// %s is part of the %s interface.\n", fn.Type(), iface.Name) |
| 60 | g.Printf("type %s func(%s) (%s)\n", fn.Type(), fn.Args, fn.Returns) |
| 61 | g.Printf("\n") |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | // Hooks struct |
| 66 | g.Printf(` |
| 67 | // Hooks defines a set of method interceptors for methods included in |
| 68 | // http.ResponseWriter as well as some others. You can think of them as |
| 69 | // middleware for the function calls they target. See Wrap for more details. |
| 70 | // |
| 71 | // For each method, the exact matching hook takes precedence. For example, |
| 72 | // WriteString calls the WriteString hook when it is configured, even if a |
| 73 | // Write hook is also configured. If the exact hook is not configured, most |
| 74 | // methods call through to the underlying ResponseWriter directly. |
| 75 | // |
| 76 | // Two compatibility fallbacks preserve the behavior users had before Wrap |
| 77 | // learned about newer optional interfaces: |
| 78 | // - If the underlying ResponseWriter implements io.StringWriter and |
| 79 | // WriteString is called, but only the Write hook is configured, WriteString |
| 80 | // is routed through the Write hook with []byte(s). If neither hook is |
| 81 | // configured, WriteString calls the underlying WriteString method directly. |
| 82 | // - If the underlying ResponseWriter implements both http.Flusher and |
| 83 | // FlushError, and FlushError is called, but only the Flush hook is |
| 84 | // configured, FlushError is routed through the Flush hook while preserving |
| 85 | // the error returned by the underlying FlushError method. If neither hook is |
| 86 | // configured, FlushError calls the underlying FlushError method directly. |
| 87 | type Hooks struct { |
| 88 | `) |
| 89 | for _, iface := range ifaces { |
| 90 | for _, fn := range iface.Funcs { |
| 91 | g.Printf("%s func(%s) %s\n", fn.Name, fn.Type(), fn.Type()) |
| 92 | } |
| 93 | } |
| 94 | g.Printf("}\n") |
| 95 | |
| 96 | // Wrap func |