sources and sinks should use io.Reader/Writer