1 // Copyright 2017 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 import Foundation
16 
17 // The I/O code below is derived from Apple's swift-protobuf project.
18 // https://github.com/apple/swift-protobuf
19 // BEGIN swift-protobuf derivation
20 
21 #if os(Linux)
22   import Glibc
23 #else
24   import Darwin.C
25 #endif
26 
27 enum PluginError: Error {
28   /// Raised for any errors reading the input
29   case readFailure
30 }
31 
32 // Alias clib's write() so Stdout.write(bytes:) can call it.
33 private let _write = write
34 
35 class Stdin {
readallnull36   static func readall() throws -> Data {
37     let fd: Int32 = 0
38     let buffSize = 32
39     var buff = [UInt8]()
40     while true {
41       var fragment = [UInt8](repeating: 0, count: buffSize)
42       let count = read(fd, &fragment, buffSize)
43       if count < 0 {
44         throw PluginError.readFailure
45       }
46       if count < buffSize {
47         buff += fragment[0..<count]
48         return Data(bytes: buff)
49       }
50       buff += fragment
51     }
52   }
53 }
54 
55 class Stdout {
writenull56   static func write(bytes: Data) {
57     bytes.withUnsafeBytes { (p: UnsafePointer<UInt8>) -> () in
58       _ = _write(1, p, bytes.count)
59     }
60   }
61 }
62 
63 struct CodePrinter {
64   private(set) var content = ""
65   private var currentIndentDepth = 0
66   private var currentIndent = ""
67   private var atLineStart = true
68 
printnull69   mutating func print(_ text: String...) {
70     for t in text {
71       for c in t.characters {
72         if c == "\n" {
73           content.append(c)
74           atLineStart = true
75         } else {
76           if atLineStart {
77             content.append(currentIndent)
78             atLineStart = false
79           }
80           content.append(c)
81         }
82       }
83     }
84   }
85 
resetIndentnull86   mutating private func resetIndent() {
87     currentIndent = (0..<currentIndentDepth).map { Int -> String in return "  " } .joined(separator:"")
88   }
89 
indentnull90   mutating func indent() {
91     currentIndentDepth += 1
92     resetIndent()
93   }
outdentnull94   mutating func outdent() {
95     currentIndentDepth -= 1
96     resetIndent()
97   }
98 }
99 
100 // END swift-protobuf derivation
101